diff --git a/README.md b/README.md
index fcbe56c..e10d0b7 100644
--- a/README.md
+++ b/README.md
@@ -81,6 +81,16 @@ On Hyprland and Niri, admin prompts and setting up a face need a polkit agent
(for example hyprpolkitagent). Hyprland without uwsm does not start the lock
screen part by itself: the menu shows the line to add to `hyprland.conf`.
+
+Coming from plasma-face-unlock?
+
+This is the same program with a new name. Your faces and settings move over
+on their own. On Debian, Ubuntu and Fedora the repository moved too: remove the
+old `plasma-face-unlock` repository file and add the new one above. On Arch,
+`yay -S face-unlock` replaces the old package.
+
+
+
## How to use
```bash
diff --git a/packaging/build-deb.sh b/packaging/build-deb.sh
index 4b08427..aca5d2f 100755
--- a/packaging/build-deb.sh
+++ b/packaging/build-deb.sh
@@ -68,6 +68,16 @@ fi
SH
chmod 755 "$root/DEBIAN/prerm"
+# Faces, settings and PAM lines of plasma-face-unlock, the old name.
+cat > "$root/DEBIAN/postinst" <<'SH'
+#!/bin/sh
+set -e
+if [ "$1" = configure ]; then
+ face-unlock --root migrate || true
+fi
+SH
+chmod 755 "$root/DEBIAN/postinst"
+
( cd "$root" && find . -type f ! -path './DEBIAN/*' -printf '%P\0' \
| LC_ALL=C sort -z | xargs -0 md5sum > DEBIAN/md5sums )
diff --git a/packaging/deb/control b/packaging/deb/control
index bd4bed1..c06f9de 100644
--- a/packaging/deb/control
+++ b/packaging/deb/control
@@ -6,6 +6,8 @@ Architecture: @ARCH@
Maintainer: Felitendo
Depends: @DEPENDS@, bash (>= 4.2), coreutils, grep, sed, mawk | gawk, systemd, polkitd | policykit-1, qml6-module-qtquick, qml6-module-qtquick-shapes, qml6-module-qtquick-effects, qml6-module-qtquick-window, qml6-module-qtqml-workerscript
Recommends: gettext-base
+Replaces: plasma-face-unlock
+Conflicts: plasma-face-unlock
Homepage: https://github.com/LoonixTools/face-unlock
Description: face unlock for Plasma, GNOME, Hyprland and Niri
Look at the screen and it unlocks, the way a phone does. The lock screen,
@@ -13,6 +15,9 @@ Description: face unlock for Plasma, GNOME, Hyprland and Niri
of a password, on KDE Plasma, GNOME, Hyprland and Niri. A bubble at the top
of the screen shows the face being looked for, recognised or refused.
.
+ This package was called plasma-face-unlock before. It takes over its faces
+ and settings.
+ .
A photo on a phone, a tablet or a glossy print is refused by its
reflection and its straight edges. The strict photo check also wants a sign
of life (a blink, or the nose moving the way a real nose does when the head
diff --git a/packaging/rpm/face-unlock.spec b/packaging/rpm/face-unlock.spec
index 428f055..4369e56 100644
--- a/packaging/rpm/face-unlock.spec
+++ b/packaging/rpm/face-unlock.spec
@@ -45,6 +45,9 @@ Requires: polkit
Requires: systemd
Requires: qt6-qtdeclarative
Recommends: /usr/bin/gettext
+# The old name.
+Obsoletes: plasma-face-unlock < 2
+Provides: plasma-face-unlock = %{version}-%{release}
%description
Look at the screen and it unlocks, the way a phone does. The lock screen, sudo
@@ -52,6 +55,9 @@ in a terminal and the admin password prompts can take a face instead of a
password, on KDE Plasma, GNOME, Hyprland and Niri. A bubble at the top of the
screen shows the face being looked for, recognised or refused.
+This package was called plasma-face-unlock before. It takes over its faces and
+settings.
+
A photo on a phone, a tablet or a glossy print is refused by its reflection and
its straight edges. The strict photo check also wants a sign of life (a blink,
or the nose moving the way a real nose does when the head turns), which stops a
@@ -82,6 +88,10 @@ make install DESTDIR=%{buildroot} PREFIX=%{_prefix} VERSION=%{upstream_version}
%postun
%systemd_postun face-unlockd.socket face-unlockd.service
+# After the old package is gone: its faces, settings and PAM lines.
+%posttrans
+%{_bindir}/face-unlock --root migrate || :
+
%files -f %{name}.lang
%license LICENSE
%doc %{_datadir}/doc/%{name}/README.md
diff --git a/po/de.po b/po/de.po
index 88e4de6..739ea4b 100644
--- a/po/de.po
+++ b/po/de.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.0\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-23 22:32+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: German\n"
@@ -173,7 +173,7 @@ msgstr ""
"Starte das als dein eigener Benutzer, nicht als root. Wenn nötig, wird nach "
"deinem Passwort gefragt."
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "Unbekannter Befehl: %s"
@@ -669,6 +669,14 @@ msgstr "Ausprobieren"
msgid "Quit"
msgstr "Beenden"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr ""
+"Deine Gesichter und Einstellungen werden von plasma-face-unlock übernommen. "
+"Dafür ist dein Passwort nötig."
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -679,26 +687,26 @@ msgstr "Das PAM-Modul ist nicht unter %s installiert."
msgid "There is no PAM configuration for %s on this system."
msgstr "Auf diesem System gibt es keine PAM-Konfiguration für %s."
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr ""
"Dafür braucht es root, aber weder sudo noch run0 noch doas ist installiert."
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "Dieser Befehl muss als root laufen."
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "Keine gültige Einstellung: %s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "Dafür kann es nicht verwendet werden: %s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/es.po b/po/es.po
index f3424f3..d0cbaed 100644
--- a/po/es.po
+++ b/po/es.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: Spanish\n"
@@ -174,7 +174,7 @@ msgstr ""
"Ejecuta esto con tu propio usuario, no como root. Pide tu contraseña cuando "
"la necesita."
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "Comando desconocido: %s"
@@ -675,6 +675,14 @@ msgstr "Probarlo"
msgid "Quit"
msgstr "Salir"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr ""
+"Pasando tus caras y ajustes desde plasma-face-unlock. Para eso hace falta tu "
+"contraseña."
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -685,25 +693,25 @@ msgstr "El módulo PAM no está instalado en %s."
msgid "There is no PAM configuration for %s on this system."
msgstr "No hay configuración PAM para %s en este sistema."
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr "Esto necesita root, y no está instalado ni sudo, ni run0, ni doas."
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "Este comando tiene que ejecutarse como root."
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "Ajuste no válido: %s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "No se puede usar para este servicio: %s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/face-unlock.pot b/po/face-unlock.pot
index 9b6b418..866be5d 100644
--- a/po/face-unlock.pot
+++ b/po/face-unlock.pot
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 09:30+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -160,7 +160,7 @@ msgid ""
"needs to."
msgstr ""
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr ""
@@ -621,6 +621,12 @@ msgstr ""
msgid "Quit"
msgstr ""
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr ""
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -631,25 +637,25 @@ msgstr ""
msgid "There is no PAM configuration for %s on this system."
msgstr ""
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr ""
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr ""
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr ""
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr ""
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/fr.po b/po/fr.po
index 3bd1b33..e14a309 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: French\n"
@@ -176,7 +176,7 @@ msgstr ""
"Lancez ceci avec votre propre utilisateur, pas en root. Le mot de passe est "
"demandé quand il le faut."
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "Commande inconnue : %s"
@@ -679,6 +679,14 @@ msgstr "Essayer"
msgid "Quit"
msgstr "Quitter"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr ""
+"Reprise de vos visages et réglages depuis plasma-face-unlock. Cela demande "
+"votre mot de passe."
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -689,26 +697,26 @@ msgstr "Le module PAM n'est pas installé dans %s."
msgid "There is no PAM configuration for %s on this system."
msgstr "Il n'y a pas de configuration PAM pour %s sur ce système."
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr ""
"Il faut les droits root, mais ni sudo, ni run0, ni doas n'est installé."
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "Cette commande doit être lancée en root."
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "Réglage non valide : %s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "Ne peut pas servir pour ce service : %s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/it.po b/po/it.po
index 5fef2a0..ca98019 100644
--- a/po/it.po
+++ b/po/it.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: Italian\n"
@@ -172,7 +172,7 @@ msgstr ""
"Esegui questo con il tuo utente, non come root. Chiede la password quando "
"serve."
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "Comando sconosciuto: %s"
@@ -670,6 +670,14 @@ msgstr "Provalo"
msgid "Quit"
msgstr "Esci"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr ""
+"Trasferimento dei tuoi volti e delle impostazioni da plasma-face-unlock. "
+"Serve la tua password."
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -680,26 +688,26 @@ msgstr "Il modulo PAM non è installato in %s."
msgid "There is no PAM configuration for %s on this system."
msgstr "Su questo sistema non c'è una configurazione PAM per %s."
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr ""
"Servono i permessi di root, ma non è installato né sudo, né run0, né doas."
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "Questo comando deve essere eseguito come root."
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "Impostazione non valida: %s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "Non si può usare per questo servizio: %s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/ja.po b/po/ja.po
index 9526b9f..6cbe8af 100644
--- a/po/ja.po
+++ b/po/ja.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: Japanese\n"
@@ -167,7 +167,7 @@ msgstr ""
"root ではなく、自分のユーザーで実行してください。必要なときはパスワードを尋ね"
"ます。"
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "不明なコマンド: %s"
@@ -657,6 +657,12 @@ msgstr "試す"
msgid "Quit"
msgstr "終了"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr "plasma-face-unlock から顔と設定を引き継ぎます。パスワードが必要です。"
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -667,26 +673,26 @@ msgstr "PAM モジュールが %s にインストールされていません。"
msgid "There is no PAM configuration for %s on this system."
msgstr "このシステムには %s の PAM 設定がありません。"
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr ""
"root 権限が必要ですが、sudo も run0 も doas もインストールされていません。"
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "このコマンドは root で実行する必要があります。"
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "無効な設定です: %s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "このサービスには使えません: %s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/ko.po b/po/ko.po
index 40cfae7..6675792 100644
--- a/po/ko.po
+++ b/po/ko.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: Korean\n"
@@ -166,7 +166,7 @@ msgid ""
"needs to."
msgstr "root가 아닌 본인 사용자로 실행하세요. 필요하면 비밀번호를 묻습니다."
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "알 수 없는 명령: %s"
@@ -655,6 +655,13 @@ msgstr "사용해 보기"
msgid "Quit"
msgstr "끝내기"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr ""
+"plasma-face-unlock에서 얼굴과 설정을 옮겨 옵니다. 비밀번호가 필요합니다."
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -665,26 +672,26 @@ msgstr "PAM 모듈이 다음 위치에 설치되어 있지 않습니다: %s"
msgid "There is no PAM configuration for %s on this system."
msgstr "이 시스템에는 %s용 PAM 설정이 없습니다."
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr ""
"root 권한이 필요하지만 sudo, run0, doas 중 아무것도 설치되어 있지 않습니다."
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "이 명령은 root로 실행해야 합니다."
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "올바르지 않은 설정: %s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "이 서비스에는 사용할 수 없습니다: %s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/nl.po b/po/nl.po
index 0f872ad..98ef199 100644
--- a/po/nl.po
+++ b/po/nl.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: Dutch\n"
@@ -172,7 +172,7 @@ msgstr ""
"Voer dit uit als je eigen gebruiker, niet als root. Het vraagt om je "
"wachtwoord als dat nodig is."
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "Onbekende opdracht: %s"
@@ -666,6 +666,14 @@ msgstr "Uitproberen"
msgid "Quit"
msgstr "Afsluiten"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr ""
+"Je gezichten en instellingen worden overgenomen van plasma-face-unlock. "
+"Daarvoor is je wachtwoord nodig."
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -676,27 +684,27 @@ msgstr "De PAM-module is niet geïnstalleerd in %s."
msgid "There is no PAM configuration for %s on this system."
msgstr "Er is op dit systeem geen PAM-configuratie voor %s."
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr ""
"Dit heeft root nodig, maar sudo, run0 en doas zijn geen van alle "
"geïnstalleerd."
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "Deze opdracht moet als root draaien."
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "Geen geldige instelling: %s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "Hier kan het niet voor worden gebruikt: %s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/pl.po b/po/pl.po
index e7100f1..926022d 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: Polish\n"
@@ -173,7 +173,7 @@ msgstr ""
"Uruchom to jako swój użytkownik, nie jako root. Hasło zostanie zapytane, gdy "
"będzie potrzebne."
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "Nieznane polecenie: %s"
@@ -668,6 +668,12 @@ msgstr "Wypróbuj"
msgid "Quit"
msgstr "Zakończ"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr "Przenoszenie twarzy i ustawień z plasma-face-unlock. To wymaga hasła."
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -678,26 +684,26 @@ msgstr "Moduł PAM nie jest zainstalowany w %s."
msgid "There is no PAM configuration for %s on this system."
msgstr "Na tym systemie nie ma konfiguracji PAM dla %s."
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr ""
"To wymaga roota, a nie jest zainstalowane ani sudo, ani run0, ani doas."
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "To polecenie musi działać jako root."
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "Nieprawidłowe ustawienie: %s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "Nie można tego użyć dla tej usługi: %s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/pt_BR.po b/po/pt_BR.po
index b20cc1e..0e6b19e 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: Brazilian Portuguese\n"
@@ -173,7 +173,7 @@ msgstr ""
"Execute isto com o seu próprio usuário, não como root. Ele pede a sua senha "
"quando precisa."
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "Comando desconhecido: %s"
@@ -670,6 +670,14 @@ msgstr "Testar"
msgid "Quit"
msgstr "Sair"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr ""
+"Trazendo seus rostos e configurações do plasma-face-unlock. Isso precisa da "
+"sua senha."
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -680,25 +688,25 @@ msgstr "O módulo PAM não está instalado em %s."
msgid "There is no PAM configuration for %s on this system."
msgstr "Não há configuração PAM para %s neste sistema."
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr "Isto precisa de root, e nem sudo, nem run0, nem doas está instalado."
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "Este comando precisa ser executado como root."
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "Configuração inválida: %s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "Não pode ser usado para este serviço: %s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/ru.po b/po/ru.po
index f443dc8..8d0b46d 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: Russian\n"
@@ -173,7 +173,7 @@ msgstr ""
"Запускайте это от своего пользователя, не от root. Пароль будет запрошен, "
"когда он понадобится."
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "Неизвестная команда: %s"
@@ -669,6 +669,14 @@ msgstr "Попробовать"
msgid "Quit"
msgstr "Выход"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr ""
+"Переносим ваши лица и настройки из plasma-face-unlock. Для этого нужен ваш "
+"пароль."
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -679,25 +687,25 @@ msgstr "Модуль PAM не установлен в %s."
msgid "There is no PAM configuration for %s on this system."
msgstr "В этой системе нет настройки PAM для %s."
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr "Для этого нужен root, но не установлен ни sudo, ни run0, ни doas."
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "Эту команду нужно запускать от root."
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "Недопустимая настройка: %s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "Для этой службы использовать нельзя: %s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/tr.po b/po/tr.po
index a805fae..28c0a5e 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: Turkish\n"
@@ -168,7 +168,7 @@ msgstr ""
"Bunu root olarak değil, kendi kullanıcınızla çalıştırın. Gerektiğinde "
"parolanızı sorar."
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "Bilinmeyen komut: %s"
@@ -661,6 +661,14 @@ msgstr "Dene"
msgid "Quit"
msgstr "Çık"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr ""
+"Yüzleriniz ve ayarlarınız plasma-face-unlock'tan aktarılıyor. Bunun için "
+"parolanız gerekiyor."
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -671,25 +679,25 @@ msgstr "PAM modülü şu konumda kurulu değil: %s"
msgid "There is no PAM configuration for %s on this system."
msgstr "Bu sistemde %s için PAM yapılandırması yok."
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr "Bunun için root gerekli, ama ne sudo ne run0 ne de doas kurulu."
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "Bu komut root olarak çalışmalı."
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "Geçerli bir ayar değil: %s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "Bunun için kullanılamaz: %s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/uk.po b/po/uk.po
index 53e8e5b..8201bb5 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: Ukrainian\n"
@@ -174,7 +174,7 @@ msgstr ""
"Запускайте це від свого користувача, не від root. Пароль буде запитано, коли "
"він знадобиться."
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "Невідома команда: %s"
@@ -669,6 +669,14 @@ msgstr "Спробувати"
msgid "Quit"
msgstr "Вийти"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr ""
+"Переносимо ваші обличчя й налаштування з plasma-face-unlock. Для цього "
+"потрібен ваш пароль."
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -679,25 +687,25 @@ msgstr "Модуль PAM не встановлено в %s."
msgid "There is no PAM configuration for %s on this system."
msgstr "У цій системі немає налаштування PAM для %s."
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr "Для цього потрібен root, але не встановлено ні sudo, ні run0, ні doas."
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "Цю команду треба запускати від root."
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "Неприпустиме налаштування: %s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "Для цієї служби використати не можна: %s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 4a8af1f..e4eabc9 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: face-unlock 1.0.1\n"
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
-"POT-Creation-Date: 2026-09-25 09:29+0200\n"
+"POT-Creation-Date: 2026-09-25 08:20+0200\n"
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
"Last-Translator: Felitendo\n"
"Language-Team: Chinese (simplified)\n"
@@ -159,7 +159,7 @@ msgid ""
"needs to."
msgstr "请以你自己的用户运行,不要用 root。需要时会询问你的密码。"
-#: src/face-unlock:222 src/lib/system.sh:89
+#: src/face-unlock:226 src/lib/system.sh:93
#, sh-printf-format
msgid "Unknown command: %s"
msgstr "未知命令:%s"
@@ -622,6 +622,12 @@ msgstr "试一试"
msgid "Quit"
msgstr "退出"
+#: src/lib/migrate.sh:119
+msgid ""
+"Moving your faces and settings over from plasma-face-unlock. That needs your "
+"password."
+msgstr "正在从 plasma-face-unlock 迁移你的人脸和设置。这需要你的密码。"
+
#: src/lib/pam.sh:132
#, sh-printf-format
msgid "The PAM module is not installed at %s."
@@ -632,25 +638,25 @@ msgstr "PAM 模块未安装在 %s。"
msgid "There is no PAM configuration for %s on this system."
msgstr "此系统上没有 %s 的 PAM 配置。"
-#: src/lib/system.sh:47
+#: src/lib/system.sh:48
msgid "This needs root, and neither sudo, run0 nor doas is installed."
msgstr "这需要 root 权限,但 sudo、run0 和 doas 都没有安装。"
-#: src/lib/system.sh:56
+#: src/lib/system.sh:57
msgid "This command has to run as root."
msgstr "此命令必须以 root 运行。"
-#: src/lib/system.sh:64
+#: src/lib/system.sh:65
#, sh-printf-format
msgid "Not a valid setting: %s=%s"
msgstr "无效的设置:%s=%s"
-#: src/lib/system.sh:75
+#: src/lib/system.sh:76
#, sh-printf-format
msgid "Not a service this can be used for: %s"
msgstr "不能用于此服务:%s"
-#: src/lib/system.sh:131
+#: src/lib/system.sh:135
#, sh-printf-format
msgid ""
"Hyprland does not start the lock screen agent by itself. Add this line to %s:"
diff --git a/src/face-unlock b/src/face-unlock
index 3a67b05..7fb1189 100644
--- a/src/face-unlock
+++ b/src/face-unlock
@@ -23,12 +23,12 @@ FU_SELF="$(readlink -f "${BASH_SOURCE[0]}")"
# An environment that points the libraries somewhere else is ignored then.
if [[ $EUID -eq 0 ]]; then
unset FU_LIBDIR FU_LIBEXECDIR FU_LOCALEDIR FU_PAMDIR FU_CTL FU_AGENT FU_PAM_MODULE FU_SYSCONFIG \
- FU_PAM_ETC_DIR FU_PAM_VENDOR_DIRS
+ FU_PAM_ETC_DIR FU_PAM_VENDOR_DIRS FU_OLD_SYSDIR FU_OLD_STATEDIR FU_STATEDIR FU_SYSTEMD_ETC
fi
FU_LIBDIR="${FU_LIBDIR:-@LIBDIR@}"
-for _mod in common config daemon pam system menu; do
+for _mod in common config daemon pam system migrate menu; do
# shellcheck source=/dev/null
if ! source "$FU_LIBDIR/$_mod.sh"; then
printf 'face-unlock: cannot load %s/%s.sh\n' "$FU_LIBDIR" "$_mod" >&2
@@ -205,6 +205,10 @@ main() {
exit 2
fi
+ case "$cmd" in
+ ''|enable|disable|setup|add|enroll|faces|list|remove|delete|test|try) fu_migrate ;;
+ esac
+
case "$cmd" in
enable) fu_do_enable ;;
disable) fu_do_disable ;;
diff --git a/src/lib/migrate.sh b/src/lib/migrate.sh
new file mode 100644
index 0000000..50d03ca
--- /dev/null
+++ b/src/lib/migrate.sh
@@ -0,0 +1,121 @@
+# shellcheck shell=bash
+#
+# Moving over from plasma-face-unlock, the old name.
+#
+# The packages run `face-unlock --root migrate` when they are installed. The
+# command runs it too (through sudo) when it finds something left over, for
+# anybody who built it from source. This user's own settings need no root and
+# are moved every time the command starts.
+
+FU_OLD_NAME="plasma-face-unlock"
+FU_OLD_PAM_MARK="# plasma-face-unlock: the face first, the password if that does not work"
+FU_OLD_PAM_WRAPPER_MARK="# Written by plasma-face-unlock."
+
+# Overridable for the tests only, like the PAM directories.
+FU_OLD_SYSDIR="${FU_OLD_SYSDIR:-/etc/$FU_OLD_NAME}"
+FU_OLD_STATEDIR="${FU_OLD_STATEDIR:-/var/lib/$FU_OLD_NAME}"
+FU_STATEDIR="${FU_STATEDIR:-/var/lib/$FU_NAME}"
+FU_SYSTEMD_ETC="${FU_SYSTEMD_ETC:-/etc/systemd/system}"
+
+_fu_old_socket_link() {
+ printf '%s/sockets.target.wants/%sd.socket\n' "$FU_SYSTEMD_ETC" "$FU_OLD_NAME"
+}
+
+# _fu_pam_has_old
+_fu_pam_has_old() {
+ local file
+ file="$(fu_pam_etc "$1")"
+ [[ -r $file ]] && grep -q 'pam_plasma_face_unlock\.so' "$file"
+}
+
+# _fu_pam_drop_old (root)
+_fu_pam_drop_old() {
+ local file content
+ file="$(fu_pam_etc "$1")"
+ if head -n 3 "$file" | grep -qF "$FU_OLD_PAM_WRAPPER_MARK"; then
+ rm -f -- "$file"
+ return
+ fi
+ content="$(awk -v mark="$FU_OLD_PAM_MARK" '
+ $0 == mark { next }
+ /pam_plasma_face_unlock\.so/ { next }
+ { print }
+ ' "$file")" || return 1
+ _fu_pam_replace "$file" "$content"
+}
+
+# fu_migrate_system (root)
+# The system settings, the faces, sudo and admin prompts and the daemon's
+# socket, as plasma-face-unlock left them.
+fu_migrate_system() {
+ local service link
+
+ if [[ -d $FU_OLD_SYSDIR ]]; then
+ if [[ -f $FU_OLD_SYSDIR/config && ! -e $FU_SYSCONFIG ]]; then
+ install -D -m 0644 "$FU_OLD_SYSDIR/config" "$FU_SYSCONFIG" || return 1
+ fi
+ rm -rf -- "$FU_OLD_SYSDIR"
+ fi
+
+ if [[ -d $FU_OLD_STATEDIR ]]; then
+ # Faces already set up under the new name win.
+ if [[ -d $FU_OLD_STATEDIR/users ]] && ! compgen -G "$FU_STATEDIR/users/*" > /dev/null; then
+ install -d -m 0700 "$FU_STATEDIR" || return 1
+ rm -rf -- "$FU_STATEDIR/users"
+ mv -- "$FU_OLD_STATEDIR/users" "$FU_STATEDIR/users" || return 1
+ fi
+ rm -rf -- "$FU_OLD_STATEDIR"
+ fi
+
+ for service in "${FU_PAM_SERVICES[@]}"; do
+ _fu_pam_has_old "$service" || continue
+ _fu_pam_drop_old "$service" && fu_pam_enable "$service"
+ done
+
+ link="$(_fu_old_socket_link)"
+ if [[ -L $link ]]; then
+ systemctl disable --now "${FU_OLD_NAME}d.socket" > /dev/null 2>&1 || true
+ rm -f -- "$link"
+ systemctl enable --now "$FU_UNIT_SOCKET" > /dev/null 2>&1 || true
+ fi
+ return 0
+}
+
+# fu_migrate_pending
+# Whether something needs fu_migrate_system.
+fu_migrate_pending() {
+ local service
+ [[ -d $FU_OLD_SYSDIR || -d $FU_OLD_STATEDIR || -L $(_fu_old_socket_link) ]] && return 0
+ for service in "${FU_PAM_SERVICES[@]}"; do
+ _fu_pam_has_old "$service" && return 0
+ done
+ return 1
+}
+
+# fu_migrate_user
+# This user's settings and the agent's service.
+fu_migrate_user() {
+ local old="$FU_XDG_CONFIG/$FU_OLD_NAME" link
+ if [[ -d $old ]]; then
+ if [[ -e $FU_CONFDIR ]]; then
+ rm -rf -- "$old"
+ else
+ mv -- "$old" "$FU_CONFDIR"
+ fi
+ fi
+ link="$FU_XDG_CONFIG/systemd/user/graphical-session.target.wants/$FU_OLD_NAME-agent.service"
+ if [[ -L $link ]]; then
+ systemctl --user disable --now "$FU_OLD_NAME-agent.service" > /dev/null 2>&1 || true
+ rm -f -- "$link"
+ fu_agent_available && fu_agent_enable
+ fi
+ return 0
+}
+
+# fu_migrate
+fu_migrate() {
+ fu_migrate_user
+ fu_migrate_pending || return 0
+ fu_say " $(fu_msg "Moving your faces and settings over from plasma-face-unlock. That needs your password.")"
+ fu_root migrate
+}
diff --git a/src/lib/system.sh b/src/lib/system.sh
index f4cb828..714146a 100644
--- a/src/lib/system.sh
+++ b/src/lib/system.sh
@@ -13,6 +13,7 @@
# --root pam-disable
# --root socket-enable start the daemon's socket, and at boot
# --root socket-disable
+# --root migrate move over from plasma-face-unlock, see migrate.sh
FU_SELF="${FU_SELF:-$(readlink -f "${BASH_SOURCE[1]:-$0}")}"
@@ -85,6 +86,9 @@ fu_root_verb() {
socket-disable)
systemctl disable --now "$FU_UNIT_SOCKET" > /dev/null 2>&1
;;
+ migrate)
+ fu_migrate_system
+ ;;
*)
fu_bad "$(fu_msg "Unknown command: %s" "$verb")"
return 1
diff --git a/tests/test_pam.sh b/tests/test_pam.sh
index efd23bd..45bf7a3 100644
--- a/tests/test_pam.sh
+++ b/tests/test_pam.sh
@@ -10,6 +10,8 @@
# When the pam_harness from the build is there, the files that come out are
# also run through real PAM, with the module missing on purpose: the dash in
# front of the line has to make PAM skip it without a word.
+#
+# Last, moving over from plasma-face-unlock: its PAM lines, settings and faces.
# check() runs its second argument with eval, so that is quoted on purpose.
# shellcheck disable=SC2016
@@ -29,6 +31,10 @@ source "$FU_LIBDIR/common.sh"
source "$FU_LIBDIR/config.sh"
# shellcheck source=/dev/null
source "$FU_LIBDIR/pam.sh"
+# shellcheck source=/dev/null
+source "$FU_LIBDIR/system.sh"
+# shellcheck source=/dev/null
+source "$FU_LIBDIR/migrate.sh"
FU_PAM_MODULE="$tmp/lib/pam_face_unlock.so"
mkdir -p "$tmp/lib" "$tmp/etc" "$tmp/vendor"
@@ -117,6 +123,73 @@ check "vendor polkit-1: turning it off removes our file" '[[ ! -e $tmp/etc/polki
# No configuration at all.
check "an unknown service is refused" '! fu_pam_enable nosuchservice 2>/dev/null'
+# ---------------------------------------------------------------------------
+# Moving over from plasma-face-unlock
+# ---------------------------------------------------------------------------
+
+FU_OLD_SYSDIR="$tmp/old-etc"
+FU_OLD_STATEDIR="$tmp/old-state"
+FU_STATEDIR="$tmp/state"
+FU_SYSCONFIG="$tmp/new-etc/config"
+FU_SYSTEMD_ETC="$tmp/systemd"
+old_module=/usr/lib/security/pam_plasma_face_unlock.so
+
+# What plasma-face-unlock wrote is what this writes, under the old name.
+make_old() {
+ sed -i -e "s|^$FU_PAM_MARK\$|$FU_OLD_PAM_MARK|" -e "s|$FU_PAM_WRAPPER_MARK|$FU_OLD_PAM_WRAPPER_MARK|" \
+ -e "s|$FU_PAM_MODULE|$old_module|" "$1"
+}
+
+for layout in arch_sudo debian_sudo fedora_sudo; do
+ printf '%s\n' "${!layout}" > "$tmp/etc/sudo"
+ cp "$tmp/etc/sudo" "$tmp/original"
+ fu_pam_enable sudo
+ make_old "$tmp/etc/sudo"
+ check "$layout: the old line is found" '_fu_pam_has_old sudo && ! fu_pam_enabled sudo && fu_migrate_pending'
+
+ fu_migrate_system
+ check "$layout: moved over to the new line" 'fu_pam_enabled sudo && ! _fu_pam_has_old sudo'
+ check "$layout: the old comment is gone" '! grep -qF "$FU_OLD_PAM_MARK" "$tmp/etc/sudo"'
+ check "$layout: nothing is left over" '! fu_migrate_pending'
+
+ fu_pam_disable sudo
+ check "$layout: off again gives back the file from before" 'cmp -s "$tmp/etc/sudo" "$tmp/original"'
+ rm -f "$tmp/etc/sudo"
+done
+
+fu_pam_enable polkit-1
+make_old "$tmp/etc/polkit-1"
+fu_migrate_system
+check "vendor polkit-1: moved over to a file of the new name" 'grep -qF "$FU_PAM_WRAPPER_MARK" "$tmp/etc/polkit-1" && ! grep -q plasma "$tmp/etc/polkit-1"'
+fu_pam_disable polkit-1
+
+mkdir -p "$FU_OLD_SYSDIR" "$FU_OLD_STATEDIR/users"
+echo 'Liveness=heavy' > "$FU_OLD_SYSDIR/config"
+echo '{}' > "$FU_OLD_STATEDIR/users/1000.json"
+check "old settings and faces are found" 'fu_migrate_pending'
+fu_migrate_system
+check "the system settings moved" '[[ $(cat "$FU_SYSCONFIG") == Liveness=heavy && ! -e $FU_OLD_SYSDIR ]]'
+check "the faces moved" '[[ $(cat "$FU_STATEDIR/users/1000.json") == "{}" && ! -e $FU_OLD_STATEDIR ]]'
+
+mkdir -p "$FU_OLD_STATEDIR/users"
+echo old > "$FU_OLD_STATEDIR/users/1000.json"
+fu_migrate_system
+check "faces set up under the new name win" '[[ $(cat "$FU_STATEDIR/users/1000.json") == "{}" && ! -e $FU_OLD_STATEDIR ]]'
+check "nothing is left over at the end" '! fu_migrate_pending'
+
+# This user's side, with systemctl only written down.
+# shellcheck disable=SC2329 # called by fu_migrate_user
+systemctl() { printf '%s\n' "$*" >> "$tmp/systemctl"; }
+FU_XDG_CONFIG="$tmp/home-config"
+FU_CONFDIR="$FU_XDG_CONFIG/face-unlock"
+mkdir -p "$FU_XDG_CONFIG/plasma-face-unlock" "$FU_XDG_CONFIG/systemd/user/graphical-session.target.wants"
+echo 'Enabled=yes' > "$FU_XDG_CONFIG/plasma-face-unlock/config"
+ln -s /nowhere "$FU_XDG_CONFIG/systemd/user/graphical-session.target.wants/plasma-face-unlock-agent.service"
+XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-$tmp}" fu_migrate_user
+check "user settings moved" '[[ $(cat "$FU_CONFDIR/config") == Enabled=yes && ! -e $FU_XDG_CONFIG/plasma-face-unlock ]]'
+check "the old agent is off and the new one on" 'grep -q "disable --now plasma-face-unlock-agent" "$tmp/systemctl" && grep -q "enable --now face-unlock-agent" "$tmp/systemctl"'
+unset -f systemctl
+
# ---------------------------------------------------------------------------
# Through real PAM
# ---------------------------------------------------------------------------