34 Commits

Author SHA1 Message Date
fc7e058e93 Release 1.94.0 2021-08-20 13:59:06 +00:00
ff4ba1da47 data: Allow access to hidraw devices
The elanspi driver needs access to a hidraw device in order to reset the
SPI reader.
2021-08-20 13:59:06 +00:00
626128a0fa device: Remove local storage prints if they've been removed from device
If a print we have stored locally is not available in device anymore, we
need to cleanup the local database.

We do not get a proper DATA_NOT_FOUND error for most devices (indeed, at
this point no device does this properly). As such, do this when we see a
DATA_NOT_FOUND error and the first time that we get a verify-no-match
results on a device which is capable of listing all known prints.

Co-Authored-by: Marco Trevisan (Treviño) <mail@3v1n0.net>
2021-08-19 18:22:36 +02:00
0bba073dff device: Handle data not-found error as verify-no-match
In case we got a data-not-found error, it means that the device has not
such prints stored, and thus the verification failed, and there's no
need to expose the internal reasons to fprintd clients.
2021-08-18 13:09:38 +02:00
ec74c849be Translated using Weblate (Indonesian)
Currently translated at 100.0% (60 of 60 strings)

Co-authored-by: Andika Triwidada <andika@gmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/fprintd/fprintd/id/
Translation: fprintd/fprintd
2021-08-17 04:04:53 +02:00
e09d90c81b Update ca.po 2021-08-15 12:03:43 +00:00
e3b0d52ce5 device: Catch client disconnect during Release
If the client disconnected while the release call was stopping the
current action, then the disconnect will be processed. This means that
the device can be closed already and the session is destroyed.

Add a check for this, in the same way that the vanished handler deals
with this corner case.
2021-08-11 08:58:26 +00:00
70182083a1 Implement suspend/resume handling 2021-08-09 13:25:11 +02:00
66e7df1105 Keep alive fprintd if any device is WARM or HOT
This renames the internal "in-use" property to "busy" and redefines the
value to be TRUE either if a client is connected or if the device is
considered WARM or HOT.

This prevents fprintd shutdown while devices are warm in order to ensure
that the libfprint hardware protection is functional.
2021-08-09 13:25:11 +02:00
96b911913e data: Allow tuning USB parameters
Newer libfprint versions try to tune the wakeup and persist option of
USB devices. Add access rules to permit this.
2021-08-06 15:31:24 +02:00
37e6939fa9 tests: Verify PAM VerifyStop/disconnect behaviour
For verify-match, the PAM module should simply drop off the bus. In
other cases it should correctly run VerifyStop and Release the device.
Verify this for verify-match and verify-no-match.
2021-08-02 13:00:43 +02:00
bb23b7e9d0 pam: Immediately return verify-match/verify-no-match
In the verify-match case, this means disconnecting from the bus rather
than stopping the verification. This is the only way to make sure that
the result is immediately reported and we do not wait for the device to
be idle again (which generally means waiting for finger removal).

In the verify-no-match case we simply send the string first before the
operation is stopped. An exceeded retry limit is only reported after
VerifyStop has finished.
2021-08-02 13:00:43 +02:00
80eb673e83 tests: Remove broken test_verify_stop_restarts_immediately test
Before VerifyStart can be called again the current verify operation
needs to be completed. This requires waiting for VerifyStop to happen.

As such, remove the test, which is expected to fail randomly.
2021-08-02 13:00:43 +02:00
88d7d97c0d device: Remove incorrect comment about delaying verify-no-match result
We report a verify-match/verify-no-match immediately to the user. The
comment is not accurate.
2021-08-02 13:00:43 +02:00
6bc19c8892 tests: Speed up tests by only using parts of the image
We just need large enough samples to tell them apart correctly. For this
a 128x128 area from the center of each image is sufficient.

This speeds up the test run considerably. Other ways of achieving this
could be to also lower the number of enroll steps for the image device.
2021-07-31 11:53:33 +02:00
c690542e7c ci: Conveniently expose coverage report 2021-07-31 11:53:33 +02:00
5f6e80de01 file_storage: Ensure username/finger match our expectations
Otherwise we would need to track this separately, which would be a bit
of a pain.

The alternative would be simply overriding the values.
2021-07-30 23:52:00 +02:00
3c8ac241b8 tests: Try to show backtrace when killed by SIGTERM
This means that we may manage to show a backtrace if meson kills the
test process due to a timeout.
2021-07-30 23:52:00 +02:00
2bf6d6a266 device: Print error if deletion fails during garbage collection 2021-07-30 23:52:00 +02:00
be45b44337 meson: Set GLIB_VERSION_{MIN_REQUIRED,MAX_ALLOWED}
To help catch errors where we accidentally use the wrong symbols.

Closes: #42
2021-07-30 15:52:22 +02:00
572c119fd4 device: Do not use GLib 2.62 API to extend GPtrArray
We are currently only depending on 2.56.
2021-07-30 15:52:22 +02:00
980bab5135 device: Do not use GLib 2.58 API to pop from GPtrArray
We currently only depend on GLib 2.52.
2021-07-30 15:52:22 +02:00
161278cacd device: Add a memory barrier when getting session pointer
The test suite ran into a very rare error where it seemed to get stuck
during authorization. A possible explanation is that the priv->_session
pointer re-fetching is optimized away and the pointer just continues to
contain the invalid placeholder rather than an updated value.

Use g_atomic_pointer_get in order to avoid this possibility entirely.
2021-07-26 13:09:13 +00:00
2dd1cd8fc3 Translated using Weblate (French)
Currently translated at 100.0% (60 of 60 strings)

Co-authored-by: Claude Paroz <claude@2xlibre.net>
Translate-URL: https://translate.fedoraproject.org/projects/fprintd/fprintd/fr/
Translation: fprintd/fprintd
2021-07-25 14:04:40 +02:00
0de01da150 Translated using Weblate (Polish)
Currently translated at 100.0% (60 of 60 strings)

Co-authored-by: Piotr Drąg <piotrdrag@gmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/fprintd/fprintd/pl/
Translation: fprintd/fprintd
2021-07-24 13:08:32 +02:00
0844002b78 Translated using Weblate (Finnish)
Currently translated at 100.0% (60 of 60 strings)

Co-authored-by: Jan Kuparinen <copper_fin@hotmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/fprintd/fprintd/fi/
Translation: fprintd/fprintd
2021-07-23 14:04:35 +02:00
9ae3c16f2d tests: Pull more OutputChecker fixes
While debugging the g-s-d testsuite a few more issues in the
OutputChecker code came up. Pull in these fixes ensuring that EOF and
the read side FD are handled correctly.
2021-07-23 13:50:52 +02:00
f4995dcabe tests: Pull OutputChecker fixes
Mark the thread as daemon. Also use poll and fix a wrong variable
reference.
2021-07-19 21:38:25 +00:00
8c0876ae49 Translated using Weblate (Korean)
Currently translated at 100.0% (60 of 60 strings)

Co-authored-by: simmon <simmon@nplob.com>
Translate-URL: https://translate.fedoraproject.org/projects/fprintd/fprintd/ko/
Translation: fprintd/fprintd
2021-07-16 22:04:35 +02:00
3a96b6f2f0 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (60 of 60 strings)

Co-authored-by: Rafael Fontenelle <rafaelff@gnome.org>
Translate-URL: https://translate.fedoraproject.org/projects/fprintd/fprintd/pt_BR/
Translation: fprintd/fprintd
2021-07-16 22:04:35 +02:00
688f9b0acf Translated using Weblate (Swedish)
Currently translated at 100.0% (60 of 60 strings)

Co-authored-by: Anders Jonsson <anders.jonsson@norsjovallen.se>
Translate-URL: https://translate.fedoraproject.org/projects/fprintd/fprintd/sv/
Translation: fprintd/fprintd
2021-07-16 22:04:35 +02:00
5b9e237884 Translated using Weblate (Turkish)
Currently translated at 100.0% (60 of 60 strings)

Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/fprintd/fprintd/tr/
Translation: fprintd/fprintd
2021-07-16 22:04:35 +02:00
8288c0efc7 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (60 of 60 strings)

Co-authored-by: Yuri Chornoivan <yurchor@ukr.net>
Translate-URL: https://translate.fedoraproject.org/projects/fprintd/fprintd/uk/
Translation: fprintd/fprintd
2021-07-16 22:04:35 +02:00
0d2dbc6179 Switch to the Fedora weblate instance for translations
Closes: #78
2021-07-01 13:11:20 +02:00
26 changed files with 817 additions and 214 deletions

View File

@ -95,10 +95,11 @@ test_dev:
- ninja -C _build coverage - ninja -C _build coverage
- cat _build/meson-logs/coverage.txt - cat _build/meson-logs/coverage.txt
artifacts: artifacts:
name: log-and-coverage expose_as: 'Coverage Report'
when: always
paths: paths:
- _build/meson-logs - _build/meson-logs
- _build/meson-logs/coveragereport/index.html
expire_in: 1 week
test_dev_with_sanitizer: test_dev_with_sanitizer:
extends: extends:

View File

@ -1,8 +0,0 @@
[main]
host = https://www.transifex.com
[fprintd.fprintd-po-fprintd-pot]
file_filter = po/<lang>.po
source_file = po/fprintd.pot
source_lang = en

18
NEWS
View File

@ -1,6 +1,24 @@
This file lists notable changes in each release. For the full history of all This file lists notable changes in each release. For the full history of all
changes, see ChangeLog. changes, see ChangeLog.
Version 1.94.0:
API users, please adjust now to planned API changes in 2.0:
- EnrollStart will throw an error if the finger was enrolled already
- Interactive DBus authentication will only happen when requested
Highlights:
- Implement suspend/resume handling.
This requires writing "power/persist" and "power/wakeup" in sysfs.
- Support libfprint overheat protections
- Delete host prints when device prints disappeared
- pam: Immediately return success information
- Plenty of updated translations thanks to move to Fedora Weblate
- Fix possible race when retrieving session information
- Fix possible race when a client disconnects
- GLib 2.56 compatibility fixes
Version 1.92.0: Version 1.92.0:
API users, please adjust now to planned API changes in 2.0: API users, please adjust now to planned API changes in 2.0:

7
README
View File

@ -12,6 +12,13 @@ Licensed under the GPL version 2 or any later version (see COPYING).
A PAM login module is included in the 'pam' directory. A PAM login module is included in the 'pam' directory.
Translating
===========
fprintd and pam_fprintd are translated using weblate. Please visit
https://translate.fedoraproject.org/projects/fprintd/ to contribute
translations.
API use cases API use cases
============= =============

View File

@ -1,17 +0,0 @@
Updating translations
=====================
The update-transifex.sh script should be run regularly to both pull
translations from the Transifex service, and push new strings to translate.
Transifex.net Token Verification
================================
The list of tokens below guarantee the respective users to be able to enable
submission on components using the following repository url:
https://gitlab.freedesktop.org/libfprint/fprintd/
Tokens:
dKfMSehAGCsQ5gxT4r2DAp9PyEMsKAMp / hadess

View File

@ -40,3 +40,7 @@ NoNewPrivileges=true
ProtectClock=yes ProtectClock=yes
DeviceAllow=char-usb_device rw DeviceAllow=char-usb_device rw
DeviceAllow=char-spi rw DeviceAllow=char-spi rw
DeviceAllow=char-hidraw rw
# Allow tuning USB parameters (wakeup and persist)
ReadWritePaths=/sys/devices

View File

@ -1,5 +1,5 @@
project('fprintd', 'c', project('fprintd', 'c',
version: '1.92.0', version: '1.94.0',
license: 'GPLv2+', license: 'GPLv2+',
default_options: [ default_options: [
'buildtype=debugoptimized', 'buildtype=debugoptimized',
@ -64,7 +64,15 @@ add_project_arguments(common_cflags, language: 'c')
host_system = host_machine.system() host_system = host_machine.system()
# NOTE: Bump gdbus-codegen min version once we can depend on 2.64! # NOTE: Bump gdbus-codegen min version once we can depend on 2.64!
glib_min_version = '2.56' glib_min_version = '2.56'
libfprint_min_version = '1.92.0' libfprint_min_version = '1.94.0'
glib_version_def = 'GLIB_VERSION_@0@_@1@'.format(
glib_min_version.split('.')[0], glib_min_version.split('.')[1])
common_cflags = cc.get_supported_arguments([
'-DGLIB_VERSION_MIN_REQUIRED=' + glib_version_def,
'-DGLIB_VERSION_MAX_ALLOWED=' + glib_version_def,
])
add_project_arguments(common_cflags, language: 'c')
fprintd_installdir = get_option('prefix') / get_option('libexecdir') fprintd_installdir = get_option('prefix') / get_option('libexecdir')
fprintd_plugindir = get_option('prefix') / get_option('libdir') / meson.project_name() / 'modules' fprintd_plugindir = get_option('prefix') / get_option('libdir') / meson.project_name() / 'modules'

View File

@ -536,6 +536,14 @@ do_verify (sd_bus *bus,
data->timed_out = true; data->timed_out = true;
send_info_msg (data->pamh, _("Verification timed out")); send_info_msg (data->pamh, _("Verification timed out"));
} }
else
{
if (str_equal (data->result, "verify-no-match"))
send_err_msg (data->pamh, _("Failed to match fingerprint"));
else if (str_equal (data->result, "verify-match"))
/* Simply disconnect from bus if we return PAM_SUCCESS */
return PAM_SUCCESS;
}
/* Ignore errors from VerifyStop */ /* Ignore errors from VerifyStop */
data->verify_started = false; data->verify_started = false;
@ -557,11 +565,7 @@ do_verify (sd_bus *bus,
{ {
if (str_equal (data->result, "verify-no-match")) if (str_equal (data->result, "verify-no-match"))
{ {
send_err_msg (data->pamh, _("Failed to match fingerprint")); /* Nothing to do at this point. */
}
else if (str_equal (data->result, "verify-match"))
{
return PAM_SUCCESS;
} }
else if (str_equal (data->result, "verify-unknown-error")) else if (str_equal (data->result, "verify-unknown-error"))
{ {
@ -743,10 +747,16 @@ do_auth (pam_handle_t *pamh, const char *username)
if (claim_device (pamh, bus, data->dev, username)) if (claim_device (pamh, bus, data->dev, username))
{ {
int ret = do_verify (bus, data); int ret = do_verify (bus, data);
/* Simply disconnect from bus if we return PAM_SUCCESS */
if (ret != PAM_SUCCESS)
release_device (pamh, bus, data->dev); release_device (pamh, bus, data->dev);
sd_bus_close (bus);
return ret; return ret;
} }
sd_bus_close (bus);
return PAM_AUTHINFO_UNAVAIL; return PAM_AUTHINFO_UNAVAIL;
} }

View File

@ -10,7 +10,7 @@ msgstr ""
"Project-Id-Version: fprintd\n" "Project-Id-Version: fprintd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-06-30 14:00+0200\n" "POT-Creation-Date: 2021-06-30 14:00+0200\n"
"PO-Revision-Date: 2017-09-19 09:46+0000\n" "PO-Revision-Date: 2021-08-15 14:02+0200\n"
"Last-Translator: Robert Antoni Buj i Gelonch <rbuj@fedoraproject.org>\n" "Last-Translator: Robert Antoni Buj i Gelonch <rbuj@fedoraproject.org>\n"
"Language-Team: Catalan (http://www.transifex.com/freedesktop/fprintd/" "Language-Team: Catalan (http://www.transifex.com/freedesktop/fprintd/"
"language/ca/)\n" "language/ca/)\n"
@ -19,6 +19,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.3\n"
#: data/net.reactivated.fprint.device.policy.in:13 #: data/net.reactivated.fprint.device.policy.in:13
msgid "Verify a fingerprint" msgid "Verify a fingerprint"
@ -263,7 +264,7 @@ msgstr "Passeu el dit un altre cop"
#: pam/fingerprint-strings.h:176 pam/fingerprint-strings.h:204 #: pam/fingerprint-strings.h:176 pam/fingerprint-strings.h:204
msgid "Swipe was too short, try again" msgid "Swipe was too short, try again"
msgstr "Lectura incorrecta, torneu-ho a intentar" msgstr "Lectura incorrecta. Torneu-ho a intentar"
#: pam/fingerprint-strings.h:178 pam/fingerprint-strings.h:206 #: pam/fingerprint-strings.h:178 pam/fingerprint-strings.h:206
msgid "Your finger was not centered, try swiping your finger again" msgid "Your finger was not centered, try swiping your finger again"
@ -275,13 +276,12 @@ msgstr "Retireu el dit i intenteu passar el dit de nou"
#: pam/pam_fprintd.c:537 #: pam/pam_fprintd.c:537
msgid "Verification timed out" msgid "Verification timed out"
msgstr "" msgstr "S'ha esgotat el temps d'espera de la verificació"
#: pam/pam_fprintd.c:560 #: pam/pam_fprintd.c:560
#, fuzzy
msgid "Failed to match fingerprint" msgid "Failed to match fingerprint"
msgstr "Comprova una empremta" msgstr "L'empremta no coincideix"
#: pam/pam_fprintd.c:576 #: pam/pam_fprintd.c:576
msgid "An unknown error occurred" msgid "An unknown error occurred"
msgstr "" msgstr "Hi ha hagut un error desconegut"

View File

@ -6,20 +6,22 @@
# Jiri Grönroos <jiri.gronroos@iki.fi>, 2013,2018 # Jiri Grönroos <jiri.gronroos@iki.fi>, 2013,2018
# Kimmo Kujansuu <mrkujansuu@gmail.com>, 2019 # Kimmo Kujansuu <mrkujansuu@gmail.com>, 2019
# Ville Skyttä <ville.skytta@iki.fi>, 2011,2016 # Ville Skyttä <ville.skytta@iki.fi>, 2011,2016
# Jan Kuparinen <copper_fin@hotmail.com>, 2021.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fprintd\n" "Project-Id-Version: fprintd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-06-30 14:00+0200\n" "POT-Creation-Date: 2021-06-30 14:00+0200\n"
"PO-Revision-Date: 2019-04-19 20:32+0000\n" "PO-Revision-Date: 2021-07-23 12:04+0000\n"
"Last-Translator: Kimmo Kujansuu <mrkujansuu@gmail.com>\n" "Last-Translator: Jan Kuparinen <copper_fin@hotmail.com>\n"
"Language-Team: Finnish (http://www.transifex.com/freedesktop/fprintd/" "Language-Team: Finnish <https://translate.fedoraproject.org/projects/fprintd/"
"language/fi/)\n" "fprintd/fi/>\n"
"Language: fi\n" "Language: fi\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.7.2\n"
#: data/net.reactivated.fprint.device.policy.in:13 #: data/net.reactivated.fprint.device.policy.in:13
msgid "Verify a fingerprint" msgid "Verify a fingerprint"
@ -277,13 +279,12 @@ msgstr "Poista sormi ja yritä pyyhkäistä uudelleen"
#: pam/pam_fprintd.c:537 #: pam/pam_fprintd.c:537
msgid "Verification timed out" msgid "Verification timed out"
msgstr "" msgstr "Vahvistus aikakatkaistiin"
#: pam/pam_fprintd.c:560 #: pam/pam_fprintd.c:560
#, fuzzy
msgid "Failed to match fingerprint" msgid "Failed to match fingerprint"
msgstr "Vahvista sormenjälki" msgstr "Sormenjäljen vahvistaminen epäonnistui"
#: pam/pam_fprintd.c:576 #: pam/pam_fprintd.c:576
msgid "An unknown error occurred" msgid "An unknown error occurred"
msgstr "" msgstr "Tapahtui tuntematon virhe"

View File

@ -3,22 +3,23 @@
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# #
# Translators: # Translators:
# Claude Paroz <claude@2xlibre.net>, 2012 # Claude Paroz <claude@2xlibre.net>, 2012, 2021.
# Claude Paroz <claude@2xlibre.net>, 2011 # Claude Paroz <claude@2xlibre.net>, 2011, 2021.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fprintd\n" "Project-Id-Version: fprintd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-06-30 14:00+0200\n" "POT-Creation-Date: 2021-06-30 14:00+0200\n"
"PO-Revision-Date: 2017-09-19 09:42+0000\n" "PO-Revision-Date: 2021-07-25 12:04+0000\n"
"Last-Translator: Claude Paroz <claude@2xlibre.net>\n" "Last-Translator: Claude Paroz <claude@2xlibre.net>\n"
"Language-Team: French (http://www.transifex.com/freedesktop/fprintd/language/" "Language-Team: French <https://translate.fedoraproject.org/projects/fprintd/"
"fr/)\n" "fprintd/fr/>\n"
"Language: fr\n" "Language: fr\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.7.2\n"
#: data/net.reactivated.fprint.device.policy.in:13 #: data/net.reactivated.fprint.device.policy.in:13
msgid "Verify a fingerprint" msgid "Verify a fingerprint"
@ -41,18 +42,18 @@ msgstr ""
#: data/net.reactivated.fprint.device.policy.in:33 #: data/net.reactivated.fprint.device.policy.in:33
msgid "Select a user to enroll" msgid "Select a user to enroll"
msgstr "Choisir un utilisateur pour l'introduction" msgstr "Choisir un utilisateur pour lintroduction"
#: data/net.reactivated.fprint.device.policy.in:34 #: data/net.reactivated.fprint.device.policy.in:34
msgid "Privileges are required to enroll new fingerprints for other users." msgid "Privileges are required to enroll new fingerprints for other users."
msgstr "" msgstr ""
"Des permissions sont nécessaires pour introduire de nouvelles empreintes " "Des permissions sont nécessaires pour introduire de nouvelles empreintes "
"digitales pour d'autres utilisateurs." "digitales pour dautres utilisateurs."
#: src/device.c:690 #: src/device.c:690
#, c-format #, c-format
msgid "Device was not claimed before use" msgid "Device was not claimed before use"
msgstr "Le périphérique n'a pas été réservé avant utilisation" msgstr "Le périphérique na pas été réservé avant utilisation"
#: src/device.c:699 #: src/device.c:699
#, c-format #, c-format
@ -61,7 +62,7 @@ msgstr "Le périphérique est déjà utilisé par un autre utilisateur"
#: pam/fingerprint-strings.h:50 #: pam/fingerprint-strings.h:50
msgid "Place your finger on the fingerprint reader" msgid "Place your finger on the fingerprint reader"
msgstr "Placez votre doigt sur le lecteur d'empreintes" msgstr "Placez votre doigt sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:51 #: pam/fingerprint-strings.h:51
#, c-format #, c-format
@ -70,7 +71,7 @@ msgstr "Placez votre doigt sur %s"
#: pam/fingerprint-strings.h:52 #: pam/fingerprint-strings.h:52
msgid "Swipe your finger across the fingerprint reader" msgid "Swipe your finger across the fingerprint reader"
msgstr "Faites glisser votre doigt sur le lecteur d'empreintes" msgstr "Faites glisser votre doigt sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:53 #: pam/fingerprint-strings.h:53
#, c-format #, c-format
@ -79,7 +80,7 @@ msgstr "Faites glisser votre doigt sur %s"
#: pam/fingerprint-strings.h:55 #: pam/fingerprint-strings.h:55
msgid "Place your left thumb on the fingerprint reader" msgid "Place your left thumb on the fingerprint reader"
msgstr "Placez votre pouce gauche sur le lecteur d'empreintes" msgstr "Placez votre pouce gauche sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:56 #: pam/fingerprint-strings.h:56
#, c-format #, c-format
@ -88,7 +89,7 @@ msgstr "Placez votre pouce gauche sur %s"
#: pam/fingerprint-strings.h:57 #: pam/fingerprint-strings.h:57
msgid "Swipe your left thumb across the fingerprint reader" msgid "Swipe your left thumb across the fingerprint reader"
msgstr "Faites glisser votre pouce gauche sur le lecteur d'empreintes" msgstr "Faites glisser votre pouce gauche sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:58 #: pam/fingerprint-strings.h:58
#, c-format #, c-format
@ -97,7 +98,7 @@ msgstr "Faites glisser votre pouce gauche sur %s"
#: pam/fingerprint-strings.h:60 #: pam/fingerprint-strings.h:60
msgid "Place your left index finger on the fingerprint reader" msgid "Place your left index finger on the fingerprint reader"
msgstr "Placez votre index gauche sur le lecteur d'empreintes" msgstr "Placez votre index gauche sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:61 #: pam/fingerprint-strings.h:61
#, c-format #, c-format
@ -115,7 +116,7 @@ msgstr "Faites glisser votre index gauche sur %s"
#: pam/fingerprint-strings.h:65 #: pam/fingerprint-strings.h:65
msgid "Place your left middle finger on the fingerprint reader" msgid "Place your left middle finger on the fingerprint reader"
msgstr "Placez votre majeur gauche sur le lecteur d'empreintes" msgstr "Placez votre majeur gauche sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:66 #: pam/fingerprint-strings.h:66
#, c-format #, c-format
@ -124,7 +125,7 @@ msgstr "Placez votre majeur gauche sur %s"
#: pam/fingerprint-strings.h:67 #: pam/fingerprint-strings.h:67
msgid "Swipe your left middle finger across the fingerprint reader" msgid "Swipe your left middle finger across the fingerprint reader"
msgstr "Faites glisser votre majeur gauche sur le lecteur d'empreintes" msgstr "Faites glisser votre majeur gauche sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:68 #: pam/fingerprint-strings.h:68
#, c-format #, c-format
@ -133,7 +134,7 @@ msgstr "Faites glisser votre majeur gauche sur %s"
#: pam/fingerprint-strings.h:70 #: pam/fingerprint-strings.h:70
msgid "Place your left ring finger on the fingerprint reader" msgid "Place your left ring finger on the fingerprint reader"
msgstr "Placez votre annulaire gauche sur le lecteur d'empreintes" msgstr "Placez votre annulaire gauche sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:71 #: pam/fingerprint-strings.h:71
#, c-format #, c-format
@ -142,7 +143,7 @@ msgstr "Placez votre annulaire gauche sur %s"
#: pam/fingerprint-strings.h:72 #: pam/fingerprint-strings.h:72
msgid "Swipe your left ring finger across the fingerprint reader" msgid "Swipe your left ring finger across the fingerprint reader"
msgstr "Faites glisser votre annulaire gauche sur le lecteur d'empreintes" msgstr "Faites glisser votre annulaire gauche sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:73 #: pam/fingerprint-strings.h:73
#, c-format #, c-format
@ -151,7 +152,7 @@ msgstr "Faites glisser votre annulaire gauche sur %s"
#: pam/fingerprint-strings.h:75 #: pam/fingerprint-strings.h:75
msgid "Place your left little finger on the fingerprint reader" msgid "Place your left little finger on the fingerprint reader"
msgstr "Placez votre auriculaire gauche sur le lecteur d'empreintes" msgstr "Placez votre auriculaire gauche sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:76 #: pam/fingerprint-strings.h:76
#, c-format #, c-format
@ -160,7 +161,7 @@ msgstr "Placez votre auriculaire gauche sur %s"
#: pam/fingerprint-strings.h:77 #: pam/fingerprint-strings.h:77
msgid "Swipe your left little finger across the fingerprint reader" msgid "Swipe your left little finger across the fingerprint reader"
msgstr "Faites glisser votre auriculaire gauche sur le lecteur d'empreintes" msgstr "Faites glisser votre auriculaire gauche sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:78 #: pam/fingerprint-strings.h:78
#, c-format #, c-format
@ -169,7 +170,7 @@ msgstr "Faites glisser votre auriculaire gauche sur %s"
#: pam/fingerprint-strings.h:80 #: pam/fingerprint-strings.h:80
msgid "Place your right thumb on the fingerprint reader" msgid "Place your right thumb on the fingerprint reader"
msgstr "Placez votre pouce droit sur le lecteur d'empreintes" msgstr "Placez votre pouce droit sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:81 #: pam/fingerprint-strings.h:81
#, c-format #, c-format
@ -178,7 +179,7 @@ msgstr "Placez votre pouce droit sur %s"
#: pam/fingerprint-strings.h:82 #: pam/fingerprint-strings.h:82
msgid "Swipe your right thumb across the fingerprint reader" msgid "Swipe your right thumb across the fingerprint reader"
msgstr "Faites glisser votre pouce droit sur le lecteur d'empreintes" msgstr "Faites glisser votre pouce droit sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:83 #: pam/fingerprint-strings.h:83
#, c-format #, c-format
@ -187,7 +188,7 @@ msgstr "Faites glisser votre pouce droit sur %s"
#: pam/fingerprint-strings.h:85 #: pam/fingerprint-strings.h:85
msgid "Place your right index finger on the fingerprint reader" msgid "Place your right index finger on the fingerprint reader"
msgstr "Placez votre index droit sur le lecteur d'empreintes" msgstr "Placez votre index droit sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:86 #: pam/fingerprint-strings.h:86
#, c-format #, c-format
@ -196,7 +197,7 @@ msgstr "Placez votre index droit sur %s"
#: pam/fingerprint-strings.h:87 #: pam/fingerprint-strings.h:87
msgid "Swipe your right index finger across the fingerprint reader" msgid "Swipe your right index finger across the fingerprint reader"
msgstr "Faites glisser votre index droit sur le lecteur d'empreintes" msgstr "Faites glisser votre index droit sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:88 #: pam/fingerprint-strings.h:88
#, c-format #, c-format
@ -205,7 +206,7 @@ msgstr "Faites glisser votre index droit sur %s"
#: pam/fingerprint-strings.h:90 #: pam/fingerprint-strings.h:90
msgid "Place your right middle finger on the fingerprint reader" msgid "Place your right middle finger on the fingerprint reader"
msgstr "Placez votre majeur droit sur le lecteur d'empreintes" msgstr "Placez votre majeur droit sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:91 #: pam/fingerprint-strings.h:91
#, c-format #, c-format
@ -214,7 +215,7 @@ msgstr "Placez votre majeur droit sur %s"
#: pam/fingerprint-strings.h:92 #: pam/fingerprint-strings.h:92
msgid "Swipe your right middle finger across the fingerprint reader" msgid "Swipe your right middle finger across the fingerprint reader"
msgstr "Faites glisser votre majeur droit sur le lecteur d'empreintes" msgstr "Faites glisser votre majeur droit sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:93 #: pam/fingerprint-strings.h:93
#, c-format #, c-format
@ -223,7 +224,7 @@ msgstr "Faites glisser votre majeur droit sur %s"
#: pam/fingerprint-strings.h:95 #: pam/fingerprint-strings.h:95
msgid "Place your right ring finger on the fingerprint reader" msgid "Place your right ring finger on the fingerprint reader"
msgstr "Placez votre annulaire droit sur le lecteur d'empreintes" msgstr "Placez votre annulaire droit sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:96 #: pam/fingerprint-strings.h:96
#, c-format #, c-format
@ -232,7 +233,7 @@ msgstr "Placez votre annulaire droit sur %s"
#: pam/fingerprint-strings.h:97 #: pam/fingerprint-strings.h:97
msgid "Swipe your right ring finger across the fingerprint reader" msgid "Swipe your right ring finger across the fingerprint reader"
msgstr "Faites glisser votre annulaire droit sur le lecteur d'empreintes" msgstr "Faites glisser votre annulaire droit sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:98 #: pam/fingerprint-strings.h:98
#, c-format #, c-format
@ -241,7 +242,7 @@ msgstr "Faites glisser votre annulaire droit sur %s"
#: pam/fingerprint-strings.h:100 #: pam/fingerprint-strings.h:100
msgid "Place your right little finger on the fingerprint reader" msgid "Place your right little finger on the fingerprint reader"
msgstr "Placez votre auriculaire droit sur le lecteur d'empreintes" msgstr "Placez votre auriculaire droit sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:101 #: pam/fingerprint-strings.h:101
#, c-format #, c-format
@ -250,7 +251,7 @@ msgstr "Placez votre auriculaire droit sur %s"
#: pam/fingerprint-strings.h:102 #: pam/fingerprint-strings.h:102
msgid "Swipe your right little finger across the fingerprint reader" msgid "Swipe your right little finger across the fingerprint reader"
msgstr "Faites glisser votre auriculaire droit sur le lecteur d'empreintes" msgstr "Faites glisser votre auriculaire droit sur le lecteur dempreintes"
#: pam/fingerprint-strings.h:103 #: pam/fingerprint-strings.h:103
#, c-format #, c-format
@ -271,8 +272,7 @@ msgstr "Le glissement était trop bref, essayez une nouvelle fois"
#: pam/fingerprint-strings.h:178 pam/fingerprint-strings.h:206 #: pam/fingerprint-strings.h:178 pam/fingerprint-strings.h:206
msgid "Your finger was not centered, try swiping your finger again" msgid "Your finger was not centered, try swiping your finger again"
msgstr "" msgstr "Votre doigt nétait pas centré, essayez de le glisser une nouvelle fois"
"Votre doigt n'était pas centré, essayez de le glisser une nouvelle fois"
#: pam/fingerprint-strings.h:180 pam/fingerprint-strings.h:208 #: pam/fingerprint-strings.h:180 pam/fingerprint-strings.h:208
msgid "Remove your finger, and try swiping your finger again" msgid "Remove your finger, and try swiping your finger again"
@ -281,12 +281,12 @@ msgstr ""
#: pam/pam_fprintd.c:537 #: pam/pam_fprintd.c:537
msgid "Verification timed out" msgid "Verification timed out"
msgstr "" msgstr "Le délai de vérification a expiré"
#: pam/pam_fprintd.c:560 #: pam/pam_fprintd.c:560
msgid "Failed to match fingerprint" msgid "Failed to match fingerprint"
msgstr "Echec de reconnaissance de l'empreinte digitale" msgstr "Échec de reconnaissance de lempreinte digitale"
#: pam/pam_fprintd.c:576 #: pam/pam_fprintd.c:576
msgid "An unknown error occurred" msgid "An unknown error occurred"
msgstr "" msgstr "Une erreur inconnue est survenue"

View File

@ -3,21 +3,22 @@
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# #
# Translators: # Translators:
# Andika Triwidada <andika@gmail.com>, 2012 # Andika Triwidada <andika@gmail.com>, 2012, 2021.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fprintd\n" "Project-Id-Version: fprintd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-06-30 14:00+0200\n" "POT-Creation-Date: 2021-06-30 14:00+0200\n"
"PO-Revision-Date: 2017-09-19 09:08+0000\n" "PO-Revision-Date: 2021-08-17 02:04+0000\n"
"Last-Translator: Andika Triwidada <andika@gmail.com>\n" "Last-Translator: Andika Triwidada <andika@gmail.com>\n"
"Language-Team: Indonesian (http://www.transifex.com/freedesktop/fprintd/" "Language-Team: Indonesian <https://translate.fedoraproject.org/projects/"
"language/id/)\n" "fprintd/fprintd/id/>\n"
"Language: id\n" "Language: id\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.7.2\n"
#: data/net.reactivated.fprint.device.policy.in:13 #: data/net.reactivated.fprint.device.policy.in:13
msgid "Verify a fingerprint" msgid "Verify a fingerprint"
@ -274,13 +275,12 @@ msgstr "Angkat jari Anda, lalu coba gesekkan lagi"
#: pam/pam_fprintd.c:537 #: pam/pam_fprintd.c:537
msgid "Verification timed out" msgid "Verification timed out"
msgstr "" msgstr "Verifikasi habis waktu"
#: pam/pam_fprintd.c:560 #: pam/pam_fprintd.c:560
#, fuzzy
msgid "Failed to match fingerprint" msgid "Failed to match fingerprint"
msgstr "Periksa kebenaran sidik jari" msgstr "Gagal mencocokkan sidik jari"
#: pam/pam_fprintd.c:576 #: pam/pam_fprintd.c:576
msgid "An unknown error occurred" msgid "An unknown error occurred"
msgstr "" msgstr "Terjadi kesalahan yang tidak dikenal"

View File

@ -9,20 +9,22 @@
# Shinjo Park <kde@peremen.name>, 2015 # Shinjo Park <kde@peremen.name>, 2015
# Seong-ho Cho <darkcircle.0426@gmail.com>, 2011,2013 # Seong-ho Cho <darkcircle.0426@gmail.com>, 2011,2013
# Shinjo Park <kde@peremen.name>, 2015 # Shinjo Park <kde@peremen.name>, 2015
# simmon <simmon@nplob.com>, 2021.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fprintd\n" "Project-Id-Version: fprintd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-06-30 14:00+0200\n" "POT-Creation-Date: 2021-06-30 14:00+0200\n"
"PO-Revision-Date: 2017-09-19 09:46+0000\n" "PO-Revision-Date: 2021-07-16 20:04+0000\n"
"Last-Translator: Shinjo Park <kde@peremen.name>\n" "Last-Translator: simmon <simmon@nplob.com>\n"
"Language-Team: Korean (http://www.transifex.com/freedesktop/fprintd/language/" "Language-Team: Korean <https://translate.fedoraproject.org/projects/fprintd/"
"ko/)\n" "fprintd/ko/>\n"
"Language: ko\n" "Language: ko\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.7.1\n"
#: data/net.reactivated.fprint.device.policy.in:13 #: data/net.reactivated.fprint.device.policy.in:13
msgid "Verify a fingerprint" msgid "Verify a fingerprint"
@ -279,13 +281,12 @@ msgstr "손가락을 뗀 다음 인식기에 다시 문질러 보십시오"
#: pam/pam_fprintd.c:537 #: pam/pam_fprintd.c:537
msgid "Verification timed out" msgid "Verification timed out"
msgstr "" msgstr "인증 시간 초과"
#: pam/pam_fprintd.c:560 #: pam/pam_fprintd.c:560
#, fuzzy
msgid "Failed to match fingerprint" msgid "Failed to match fingerprint"
msgstr "지문 검증" msgstr "지문과 일치하지 않습니다"
#: pam/pam_fprintd.c:576 #: pam/pam_fprintd.c:576
msgid "An unknown error occurred" msgid "An unknown error occurred"
msgstr "" msgstr "알 수 없는 오류가 발생했습니다"

View File

@ -3,16 +3,16 @@
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# #
# Translators: # Translators:
# Piotr Drąg <piotrdrag@gmail.com>, 2012,2016 # Piotr Drąg <piotrdrag@gmail.com>, 2012,2016, 2021.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fprintd\n" "Project-Id-Version: fprintd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-06-30 14:00+0200\n" "POT-Creation-Date: 2021-06-30 14:00+0200\n"
"PO-Revision-Date: 2017-09-19 09:08+0000\n" "PO-Revision-Date: 2021-07-24 11:08+0000\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n" "Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish (http://www.transifex.com/freedesktop/fprintd/language/" "Language-Team: Polish <https://translate.fedoraproject.org/projects/fprintd/"
"pl/)\n" "fprintd/pl/>\n"
"Language: pl\n" "Language: pl\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -20,6 +20,7 @@ msgstr ""
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n"
"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n" "%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n"
"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" "%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
"X-Generator: Weblate 4.7.2\n"
#: data/net.reactivated.fprint.device.policy.in:13 #: data/net.reactivated.fprint.device.policy.in:13
msgid "Verify a fingerprint" msgid "Verify a fingerprint"
@ -278,13 +279,12 @@ msgstr ""
#: pam/pam_fprintd.c:537 #: pam/pam_fprintd.c:537
msgid "Verification timed out" msgid "Verification timed out"
msgstr "" msgstr "Weryfikacja przekroczyła czas oczekiwania"
#: pam/pam_fprintd.c:560 #: pam/pam_fprintd.c:560
#, fuzzy
msgid "Failed to match fingerprint" msgid "Failed to match fingerprint"
msgstr "Weryfikowanie odcisków palców" msgstr "Dopasowanie odcisku palca się nie powiodło"
#: pam/pam_fprintd.c:576 #: pam/pam_fprintd.c:576
msgid "An unknown error occurred" msgid "An unknown error occurred"
msgstr "" msgstr "Wystąpił nieznany błąd"

View File

@ -4,20 +4,22 @@
# #
# Translators: # Translators:
# Rafael Fontenelle <rffontenelle@gmail.com>, 2012 # Rafael Fontenelle <rffontenelle@gmail.com>, 2012
# Rafael Fontenelle <rafaelff@gnome.org>, 2021.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fprintd\n" "Project-Id-Version: fprintd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-06-30 14:00+0200\n" "POT-Creation-Date: 2021-06-30 14:00+0200\n"
"PO-Revision-Date: 2017-09-19 11:53+0000\n" "PO-Revision-Date: 2021-07-16 20:04+0000\n"
"Last-Translator: Rafael Fontenelle <rffontenelle@gmail.com>\n" "Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/freedesktop/" "Language-Team: Portuguese (Brazil) <https://translate.fedoraproject.org/"
"fprintd/language/pt_BR/)\n" "projects/fprintd/fprintd/pt_BR/>\n"
"Language: pt_BR\n" "Language: pt_BR\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.7.1\n"
#: data/net.reactivated.fprint.device.policy.in:13 #: data/net.reactivated.fprint.device.policy.in:13
msgid "Verify a fingerprint" msgid "Verify a fingerprint"
@ -271,17 +273,16 @@ msgstr "Seu dedo não estava no centro, tente pressioná-lo novamente"
#: pam/fingerprint-strings.h:180 pam/fingerprint-strings.h:208 #: pam/fingerprint-strings.h:180 pam/fingerprint-strings.h:208
msgid "Remove your finger, and try swiping your finger again" msgid "Remove your finger, and try swiping your finger again"
msgstr "Remova seu dedo e tente pressioná-lo novamente." msgstr "Remova seu dedo e tente pressioná-lo novamente"
#: pam/pam_fprintd.c:537 #: pam/pam_fprintd.c:537
msgid "Verification timed out" msgid "Verification timed out"
msgstr "" msgstr "Verificação expirou"
#: pam/pam_fprintd.c:560 #: pam/pam_fprintd.c:560
#, fuzzy
msgid "Failed to match fingerprint" msgid "Failed to match fingerprint"
msgstr "Verificar uma impressão digital" msgstr "Falha ao corresponder a impressão digital"
#: pam/pam_fprintd.c:576 #: pam/pam_fprintd.c:576
msgid "An unknown error occurred" msgid "An unknown error occurred"
msgstr "" msgstr "Ocorreu um erro desconhecido"

View File

@ -3,20 +3,22 @@
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# #
# Translators: # Translators:
# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2021.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fprintd\n" "Project-Id-Version: fprintd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-06-30 14:00+0200\n" "POT-Creation-Date: 2021-06-30 14:00+0200\n"
"PO-Revision-Date: 2017-09-19 09:08+0000\n" "PO-Revision-Date: 2021-07-16 20:04+0000\n"
"Last-Translator: Anders Jonsson <transifex@norsjovallen.se>\n" "Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
"Language-Team: Swedish (http://www.transifex.com/freedesktop/fprintd/" "Language-Team: Swedish <https://translate.fedoraproject.org/projects/fprintd/"
"language/sv/)\n" "fprintd/sv/>\n"
"Language: sv\n" "Language: sv\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.7.1\n"
#: data/net.reactivated.fprint.device.policy.in:13 #: data/net.reactivated.fprint.device.policy.in:13
msgid "Verify a fingerprint" msgid "Verify a fingerprint"
@ -273,13 +275,12 @@ msgstr "Ta bort ditt finger och prova att dra ditt finger igen"
#: pam/pam_fprintd.c:537 #: pam/pam_fprintd.c:537
msgid "Verification timed out" msgid "Verification timed out"
msgstr "" msgstr "Tidsgräns för verifiering överskreds"
#: pam/pam_fprintd.c:560 #: pam/pam_fprintd.c:560
#, fuzzy
msgid "Failed to match fingerprint" msgid "Failed to match fingerprint"
msgstr "Verifiera fingeravtryck" msgstr "Misslyckades med att matcha fingeravtryck"
#: pam/pam_fprintd.c:576 #: pam/pam_fprintd.c:576
msgid "An unknown error occurred" msgid "An unknown error occurred"
msgstr "" msgstr "Ett okänt fel inträffade"

View File

@ -5,20 +5,22 @@
# Translators: # Translators:
# Caner Başaran <basaran.caner@gmail.com>, 2014 # Caner Başaran <basaran.caner@gmail.com>, 2014
# Emin Tufan Çetin <etcetin@gmail.com>, 2020 # Emin Tufan Çetin <etcetin@gmail.com>, 2020
# Oğuz Ersen <oguzersen@protonmail.com>, 2021.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fprintd\n" "Project-Id-Version: fprintd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-06-30 14:00+0200\n" "POT-Creation-Date: 2021-06-30 14:00+0200\n"
"PO-Revision-Date: 2020-02-29 10:08+0000\n" "PO-Revision-Date: 2021-07-16 20:04+0000\n"
"Last-Translator: Emin Tufan Çetin <etcetin@gmail.com>\n" "Last-Translator: Oğuz Ersen <oguzersen@protonmail.com>\n"
"Language-Team: Turkish (http://www.transifex.com/freedesktop/fprintd/" "Language-Team: Turkish <https://translate.fedoraproject.org/projects/fprintd/"
"language/tr/)\n" "fprintd/tr/>\n"
"Language: tr\n" "Language: tr\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n>1);\n"
"X-Generator: Weblate 4.7.1\n"
#: data/net.reactivated.fprint.device.policy.in:13 #: data/net.reactivated.fprint.device.policy.in:13
msgid "Verify a fingerprint" msgid "Verify a fingerprint"
@ -147,21 +149,21 @@ msgstr "Sol yüzük parmağınızı %s üzerinde kaydırın"
#: pam/fingerprint-strings.h:75 #: pam/fingerprint-strings.h:75
msgid "Place your left little finger on the fingerprint reader" msgid "Place your left little finger on the fingerprint reader"
msgstr "Sol küçük parmağınızı parmak izi okuyucuya yerleştirin" msgstr "Sol serçe parmağınızı parmak izi okuyucuya yerleştirin"
#: pam/fingerprint-strings.h:76 #: pam/fingerprint-strings.h:76
#, c-format #, c-format
msgid "Place your left little finger on %s" msgid "Place your left little finger on %s"
msgstr "Sol küçük parmağınızı %s üzerine yerleştirin" msgstr "Sol serçe parmağınızı %s üzerine yerleştirin"
#: pam/fingerprint-strings.h:77 #: pam/fingerprint-strings.h:77
msgid "Swipe your left little finger across the fingerprint reader" msgid "Swipe your left little finger across the fingerprint reader"
msgstr "Sol küçük parmağınızı parmak izi okuyucu üzerinde kaydırın" msgstr "Sol serçe parmağınızı parmak izi okuyucu üzerinde kaydırın"
#: pam/fingerprint-strings.h:78 #: pam/fingerprint-strings.h:78
#, c-format #, c-format
msgid "Swipe your left little finger across %s" msgid "Swipe your left little finger across %s"
msgstr "Sol küçük parmağınızı %s üzerinde kaydırın" msgstr "Sol serçe parmağınızı %s üzerinde kaydırın"
#: pam/fingerprint-strings.h:80 #: pam/fingerprint-strings.h:80
msgid "Place your right thumb on the fingerprint reader" msgid "Place your right thumb on the fingerprint reader"
@ -237,21 +239,21 @@ msgstr "Sağ yüzük parmağınızı %s üzerinde kaydırın"
#: pam/fingerprint-strings.h:100 #: pam/fingerprint-strings.h:100
msgid "Place your right little finger on the fingerprint reader" msgid "Place your right little finger on the fingerprint reader"
msgstr "Sağ küçük parmağınızı parmak izi okuyucuya yerleştirin" msgstr "Sağ serçe parmağınızı parmak izi okuyucuya yerleştirin"
#: pam/fingerprint-strings.h:101 #: pam/fingerprint-strings.h:101
#, c-format #, c-format
msgid "Place your right little finger on %s" msgid "Place your right little finger on %s"
msgstr "Sağ küçük parmağınızı %s üzerine yerleştirin" msgstr "Sağ serçe parmağınızı %s üzerine yerleştirin"
#: pam/fingerprint-strings.h:102 #: pam/fingerprint-strings.h:102
msgid "Swipe your right little finger across the fingerprint reader" msgid "Swipe your right little finger across the fingerprint reader"
msgstr "Sağ küçük parmağınızı parmak izi okuyucu üzerinde kaydırın" msgstr "Sağ serçe parmağınızı parmak izi okuyucu üzerinde kaydırın"
#: pam/fingerprint-strings.h:103 #: pam/fingerprint-strings.h:103
#, c-format #, c-format
msgid "Swipe your right little finger across %s" msgid "Swipe your right little finger across %s"
msgstr "Sağ küçük parmağınızı %s üzerinde kaydırın" msgstr "Sağ serçe parmağınızı %s üzerinde kaydırın"
#: pam/fingerprint-strings.h:171 pam/fingerprint-strings.h:199 #: pam/fingerprint-strings.h:171 pam/fingerprint-strings.h:199
msgid "Place your finger on the reader again" msgid "Place your finger on the reader again"
@ -275,13 +277,12 @@ msgstr "Parmağınızı kaldırın ve yeniden kaydırmayı deneyin"
#: pam/pam_fprintd.c:537 #: pam/pam_fprintd.c:537
msgid "Verification timed out" msgid "Verification timed out"
msgstr "" msgstr "Doğrulama zaman aşımına uğradı"
#: pam/pam_fprintd.c:560 #: pam/pam_fprintd.c:560
#, fuzzy
msgid "Failed to match fingerprint" msgid "Failed to match fingerprint"
msgstr "Parmak izini doğrula" msgstr "Parmak izi eşleştirilemedi"
#: pam/pam_fprintd.c:576 #: pam/pam_fprintd.c:576
msgid "An unknown error occurred" msgid "An unknown error occurred"
msgstr "" msgstr "Bilinmeyen bir hata oluştu"

View File

@ -4,24 +4,25 @@
# #
# Translators: # Translators:
# Richard Hughes <richard@hughsie.com>, 2011 # Richard Hughes <richard@hughsie.com>, 2011
# Yuri Chornoivan <yurchor@ukr.net>, 2009, 2010, 2011, 2012 # Yuri Chornoivan <yurchor@ukr.net>, 2009, 2010, 2011, 2012, 2021.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fprintd\n" "Project-Id-Version: fprintd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-06-30 14:00+0200\n" "POT-Creation-Date: 2021-06-30 14:00+0200\n"
"PO-Revision-Date: 2017-09-19 09:08+0000\n" "PO-Revision-Date: 2021-07-16 20:04+0000\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n" "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian (http://www.transifex.com/freedesktop/fprintd/" "Language-Team: Ukrainian <https://translate.fedoraproject.org/projects/"
"language/uk/)\n" "fprintd/fprintd/uk/>\n"
"Language: uk\n" "Language: uk\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " "Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 "
"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " "? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > "
"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " "14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % "
"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" "100 >=11 && n % 100 <=14 )) ? 2: 3);\n"
"X-Generator: Weblate 4.7.1\n"
#: data/net.reactivated.fprint.device.policy.in:13 #: data/net.reactivated.fprint.device.policy.in:13
msgid "Verify a fingerprint" msgid "Verify a fingerprint"
@ -283,13 +284,12 @@ msgstr "Приберіть ваш палець і повторіть спроб
#: pam/pam_fprintd.c:537 #: pam/pam_fprintd.c:537
msgid "Verification timed out" msgid "Verification timed out"
msgstr "" msgstr "Перевищено час перевірки"
#: pam/pam_fprintd.c:560 #: pam/pam_fprintd.c:560
#, fuzzy
msgid "Failed to match fingerprint" msgid "Failed to match fingerprint"
msgstr "Перевірити відбиток" msgstr "Не вдалося встановити відповідність відбитка"
#: pam/pam_fprintd.c:576 #: pam/pam_fprintd.c:576
msgid "An unknown error occurred" msgid "An unknown error occurred"
msgstr "" msgstr "Сталася невідома помилка"

View File

@ -101,6 +101,8 @@ typedef struct
FpDevice *dev; FpDevice *dev;
SessionData *_session; SessionData *_session;
gboolean local_storage_checked;
guint verify_stop_wait_timeout_id; guint verify_stop_wait_timeout_id;
PolkitAuthority *auth; PolkitAuthority *auth;
@ -127,7 +129,7 @@ G_DEFINE_TYPE_WITH_CODE (FprintDevice, fprint_device,
enum fprint_device_properties { enum fprint_device_properties {
FPRINT_DEVICE_CONSTRUCT_DEV = 1, FPRINT_DEVICE_CONSTRUCT_DEV = 1,
FPRINT_DEVICE_IN_USE, FPRINT_DEVICE_BUSY,
}; };
enum fprint_device_signals { enum fprint_device_signals {
@ -168,7 +170,7 @@ session_data_get (FprintDevicePrivate *priv)
/* Get the current pointer and mark the pointer as "busy". */ /* Get the current pointer and mark the pointer as "busy". */
do do
{ {
cur = priv->_session; cur = g_atomic_pointer_get (&priv->_session);
/* Swap if cur is valid, otherwise busy loop. */ /* Swap if cur is valid, otherwise busy loop. */
} }
while (cur == invalid || !g_atomic_pointer_compare_and_exchange (&priv->_session, cur, invalid)); while (cur == invalid || !g_atomic_pointer_compare_and_exchange (&priv->_session, cur, invalid));
@ -205,7 +207,7 @@ session_data_set_new (FprintDevicePrivate *priv, gchar *sender, gchar *username)
/* Get the current (but not if it is busy) and put the new one in place. */ /* Get the current (but not if it is busy) and put the new one in place. */
do do
{ {
old = priv->_session; old = g_atomic_pointer_get (&priv->_session);
/* Swap if old is valid, otherwise busy loop as someone is ref'ing it currently. */ /* Swap if old is valid, otherwise busy loop as someone is ref'ing it currently. */
} }
while (old == invalid || !g_atomic_pointer_compare_and_exchange (&priv->_session, old, new)); while (old == invalid || !g_atomic_pointer_compare_and_exchange (&priv->_session, old, new));
@ -293,8 +295,10 @@ fprint_device_get_property (GObject *object, guint property_id,
g_value_set_object (value, priv->dev); g_value_set_object (value, priv->dev);
break; break;
case FPRINT_DEVICE_IN_USE: case FPRINT_DEVICE_BUSY:
g_value_set_boolean (value, g_hash_table_size (priv->clients) != 0); g_value_set_boolean (value,
g_hash_table_size (priv->clients) != 0 ||
fp_device_get_temperature (priv->dev) > FP_TEMPERATURE_COLD);
break; break;
default: default:
@ -359,6 +363,14 @@ on_finger_status_changed (FprintDevice *rdev,
g_debug ("Finger needed %d", needed); g_debug ("Finger needed %d", needed);
} }
static void
on_temperature_changed (FprintDevice *rdev,
GParamSpec *spec,
FpDevice *device)
{
g_object_notify (G_OBJECT (rdev), "busy");
}
static void static void
fprint_device_constructed (GObject *object) fprint_device_constructed (GObject *object)
{ {
@ -383,6 +395,11 @@ fprint_device_constructed (GObject *object)
rdev, G_CONNECT_SWAPPED); rdev, G_CONNECT_SWAPPED);
on_finger_status_changed (rdev, NULL, priv->dev); on_finger_status_changed (rdev, NULL, priv->dev);
g_signal_connect_object (priv->dev, "notify::temperature",
G_CALLBACK (on_temperature_changed),
rdev, G_CONNECT_SWAPPED);
on_temperature_changed (rdev, NULL, priv->dev);
G_OBJECT_CLASS (fprint_device_parent_class)->constructed (object); G_OBJECT_CLASS (fprint_device_parent_class)->constructed (object);
} }
@ -405,11 +422,11 @@ fprint_device_class_init (FprintDeviceClass *klass)
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
FPRINT_DEVICE_CONSTRUCT_DEV, pspec); FPRINT_DEVICE_CONSTRUCT_DEV, pspec);
pspec = g_param_spec_boolean ("in-use", "In use", pspec = g_param_spec_boolean ("busy", "Busy",
"Whether the device is currently in use", FALSE, "Whether the device is in use or too warm", FALSE,
G_PARAM_READABLE); G_PARAM_READABLE);
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
FPRINT_DEVICE_IN_USE, pspec); FPRINT_DEVICE_BUSY, pspec);
signals[SIGNAL_VERIFY_STATUS] = signals[SIGNAL_VERIFY_STATUS] =
g_signal_lookup ("verify-status", FPRINT_TYPE_DEVICE); g_signal_lookup ("verify-status", FPRINT_TYPE_DEVICE);
@ -460,6 +477,81 @@ _fprint_device_get_id (FprintDevice *rdev)
return priv->id; return priv->id;
} }
static void
suspend_cb (GObject *source_obj,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GTask) task = user_data;
GError *error = NULL;
fp_device_suspend_finish (FP_DEVICE (source_obj), res, &error);
if (error)
g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
}
static void
resume_cb (GObject *source_obj,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GTask) task = user_data;
GError *error = NULL;
fp_device_resume_finish (FP_DEVICE (source_obj), res, &error);
if (error)
g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
}
void
fprint_device_suspend (FprintDevice *rdev,
GAsyncReadyCallback callback,
void *user_data)
{
GTask *task = NULL;
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
/* Just forward to libfprint. */
task = g_task_new (rdev, NULL, callback, user_data);
fp_device_suspend (priv->dev, NULL, suspend_cb, task);
}
void
fprint_device_resume (FprintDevice *rdev,
GAsyncReadyCallback callback,
void *user_data)
{
GTask *task = NULL;
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
/* Just forward to libfprint. */
task = g_task_new (rdev, NULL, callback, user_data);
fp_device_resume (priv->dev, NULL, resume_cb, task);
}
void
fprint_device_suspend_finish (FprintDevice *rdev,
GAsyncResult *res,
GError **error)
{
g_task_propagate_boolean (G_TASK (res), error);
}
void
fprint_device_resume_finish (FprintDevice *rdev,
GAsyncResult *res,
GError **error)
{
g_task_propagate_boolean (G_TASK (res), error);
}
static const char * static const char *
fp_finger_to_name (FpFinger finger) fp_finger_to_name (FpFinger finger)
{ {
@ -521,7 +613,8 @@ verify_result_to_name (gboolean match, GError *error)
*/ */
if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_PROTO)) if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_PROTO))
return "verify-disconnected"; return "verify-disconnected";
else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_NOT_FOUND))
return "verify-no-match"; return "verify-no-match";
return "verify-unknown-error"; return "verify-unknown-error";
@ -891,7 +984,7 @@ _fprint_device_client_vanished (GDBusConnection *connection,
g_hash_table_remove (priv->clients, name); g_hash_table_remove (priv->clients, name);
if (g_hash_table_size (priv->clients) == 0) if (g_hash_table_size (priv->clients) == 0)
g_object_notify (G_OBJECT (rdev), "in-use"); g_object_notify (G_OBJECT (rdev), "busy");
} }
static void static void
@ -911,7 +1004,7 @@ _fprint_device_add_client (FprintDevice *rdev, const char *sender)
rdev, rdev,
NULL); NULL);
g_hash_table_insert (priv->clients, g_strdup (sender), GUINT_TO_POINTER (id)); g_hash_table_insert (priv->clients, g_strdup (sender), GUINT_TO_POINTER (id));
g_object_notify (G_OBJECT (rdev), "in-use"); g_object_notify (G_OBJECT (rdev), "busy");
} }
} }
@ -1081,6 +1174,14 @@ fprint_device_release (FprintDBusDevice *dbus_dev,
} }
session = session_data_get (priv); session = session_data_get (priv);
/* We iterated the mainloop, the session may have disappeared already. */
if (!session)
{
fprint_dbus_device_complete_release (FPRINT_DBUS_DEVICE (rdev), invocation);
return TRUE;
}
session->invocation = g_object_ref (invocation); session->invocation = g_object_ref (invocation);
priv->current_action = ACTION_CLOSE; priv->current_action = ACTION_CLOSE;
@ -1124,6 +1225,7 @@ load_all_prints (FprintDevice *rdev)
{ {
g_autoptr(GPtrArray) res = g_ptr_array_new_with_free_func (g_object_unref); g_autoptr(GPtrArray) res = g_ptr_array_new_with_free_func (g_object_unref);
GSList *user, *users = NULL; GSList *user, *users = NULL;
guint i;
users = store.discover_users (); users = store.discover_users ();
@ -1132,7 +1234,9 @@ load_all_prints (FprintDevice *rdev)
const char *username = user->data; const char *username = user->data;
g_autoptr(GPtrArray) prints = load_user_prints (rdev, username); g_autoptr(GPtrArray) prints = load_user_prints (rdev, username);
g_ptr_array_extend_and_steal (res, g_steal_pointer (&prints)); /* TODO: Use g_ptr_array_extend_and_steal with GLib >= 2.62 */
for (i = 0; i < prints->len; i++)
g_ptr_array_add (res, g_object_ref (g_ptr_array_index (prints, i)));
} }
g_slist_free_full (users, g_free); g_slist_free_full (users, g_free);
@ -1171,6 +1275,93 @@ report_verify_status (FprintDevice *rdev,
session->verify_status_reported = TRUE; session->verify_status_reported = TRUE;
} }
static void
check_local_storage (FprintDevice *rdev,
gboolean found_match,
GError *error)
{
g_autoptr(GError) err = NULL;
g_autoptr(GPtrArray) device_prints = NULL;
g_autoptr(GPtrArray) host_prints = NULL;
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
unsigned i;
g_return_if_fail (priv->current_action == ACTION_VERIFY ||
priv->current_action == ACTION_IDENTIFY);
/* This only ever sense if the device can list prints. */
if (!fp_device_has_feature (priv->dev, FP_DEVICE_FEATURE_STORAGE_LIST))
return;
/* We do not have any proper driver that correctly reports DATA_NOT_FOUND
* errors. Only synaptics, but there the feature is being disabled on the
* firmware side.
* As such, just always run a test the first time we get a match failure.
*/
if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_NOT_FOUND))
{
if (priv->local_storage_checked)
g_warning ("Device %s reported that a passed print did not exist during action %d, but we verified the local storage!",
fp_device_get_name (priv->dev), priv->current_action);
else
g_debug ("Device %s reported that a passed print did not exist during action %d",
fp_device_get_name (priv->dev), priv->current_action);
}
else if (error || priv->local_storage_checked)
{
return;
}
else if (!found_match)
{
g_debug ("Device %s failed to match during action %d, verifying local storage",
fp_device_get_name (priv->dev), priv->current_action);
}
else
{
return;
}
priv->local_storage_checked = TRUE;
device_prints = fp_device_list_prints_sync (priv->dev, NULL, &err);
if (!device_prints)
{
g_warning ("Failed to query prints: %s", err->message);
return;
}
host_prints = load_all_prints (rdev);
for (i = 0; i < host_prints->len; i++)
{
FpPrint *print = g_ptr_array_index (host_prints, i);
int r;
if (g_ptr_array_find_with_equal_func (device_prints,
print,
(GEqualFunc) fp_print_equal,
NULL))
continue;
/* Print not known by device, remove locally */
if ((r = store.print_data_delete (priv->dev,
fp_print_get_finger (print),
fp_print_get_username (print))) == 0)
{
g_message ("Deleted stored finger %d for user %s as it is unknown to device.",
fp_print_get_finger (print),
fp_print_get_username (print));
}
else
{
g_warning ("Error deleting finger %d for user %s that is unknown to device: %d!",
fp_print_get_finger (print),
fp_print_get_username (print),
r);
}
}
}
static gboolean static gboolean
can_start_action (FprintDevice *rdev, GError **error) can_start_action (FprintDevice *rdev, GError **error)
{ {
@ -1345,8 +1536,6 @@ match_cb (FpDevice *device,
cancelled = g_cancellable_is_cancelled (priv->current_cancellable); cancelled = g_cancellable_is_cancelled (priv->current_cancellable);
matched = match != NULL && cancelled == FALSE; matched = match != NULL && cancelled == FALSE;
/* No-match is reported only after the operation completes.
* This avoids problems when the operation is immediately restarted. */
report_verify_status (rdev, matched, error); report_verify_status (rdev, matched, error);
} }
@ -1389,6 +1578,8 @@ verify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
error->message); error->message);
} }
check_local_storage (rdev, match, error);
stoppable_action_completed (rdev); stoppable_action_completed (rdev);
} }
} }
@ -1432,6 +1623,8 @@ identify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
error->message); error->message);
} }
check_local_storage (rdev, match != NULL, error);
stoppable_action_completed (rdev); stoppable_action_completed (rdev);
} }
} }
@ -1506,7 +1699,9 @@ fprint_device_verify_start (FprintDBusDevice *dbus_dev,
if (gallery) if (gallery)
{ {
print = g_ptr_array_steal_index_fast (gallery, 0); /* TODO: Use g_ptr_array_remove_index_fast with GLib >= 2.58 */
print = g_object_ref (g_ptr_array_index (gallery, 0));
g_ptr_array_remove_index_fast (gallery, 0);
finger = fp_print_get_finger (print); finger = fp_print_get_finger (print);
} }
else else
@ -1931,7 +2126,8 @@ enroll_identify_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
priv->current_cancellable, priv->current_cancellable,
&error)) &error))
{ {
g_warning ("Failed to garbage collect duplicate print, cannot continue with enroll."); g_warning ("Failed to garbage collect duplicate print, cannot continue with enroll: %s",
error->message);
g_signal_emit (rdev, signals[SIGNAL_ENROLL_STATUS], 0, "enroll-duplicate", TRUE); g_signal_emit (rdev, signals[SIGNAL_ENROLL_STATUS], 0, "enroll-duplicate", TRUE);
stoppable_action_completed (rdev); stoppable_action_completed (rdev);

View File

@ -220,6 +220,14 @@ file_storage_print_data_load (FpDevice *dev,
if (r) if (r)
return r; return r;
/* Make sure the username/finger matches our expectations. */
if (fp_print_get_finger (new) != finger)
return -EINVAL;
if (g_strcmp0 (fp_print_get_username (new), username) != 0)
return -EINVAL;
/* And that the print is compatible with the device. */
if (!fp_print_compatible (new, dev)) if (!fp_print_compatible (new, dev))
return -EINVAL; return -EINVAL;

View File

@ -95,6 +95,22 @@ struct _FprintDevice
FprintDevice *fprint_device_new (FpDevice *dev); FprintDevice *fprint_device_new (FpDevice *dev);
guint32 _fprint_device_get_id (FprintDevice *rdev); guint32 _fprint_device_get_id (FprintDevice *rdev);
void fprint_device_suspend (FprintDevice *rdev,
GAsyncReadyCallback callback,
void *user_data);
void fprint_device_resume (FprintDevice *rdev,
GAsyncReadyCallback callback,
void *user_data);
void fprint_device_suspend_finish (FprintDevice *rdev,
GAsyncResult *result,
GError **error);
void fprint_device_resume_finish (FprintDevice *rdev,
GAsyncResult *res,
GError **error);
/* Print */ /* Print */
/* TODO */ /* TODO */

View File

@ -24,9 +24,14 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <fprint.h> #include <fprint.h>
#include <glib-object.h> #include <glib-object.h>
#include <gio/gunixfdlist.h>
#include "fprintd.h" #include "fprintd.h"
#define LOGIND_BUS_NAME "org.freedesktop.login1"
#define LOGIND_IFACE_NAME "org.freedesktop.login1.Manager"
#define LOGIND_OBJ_PATH "/org/freedesktop/login1"
static void fprint_manager_constructed (GObject *object); static void fprint_manager_constructed (GObject *object);
static gboolean fprint_manager_get_devices (FprintManager *manager, static gboolean fprint_manager_get_devices (FprintManager *manager,
GPtrArray **devices, GPtrArray **devices,
@ -43,6 +48,9 @@ typedef struct
FpContext *context; FpContext *context;
gboolean no_timeout; gboolean no_timeout;
guint timeout_id; guint timeout_id;
gint prepare_for_sleep_pending;
guint prepare_for_sleep_id;
gint sleep_inhibit_fd;
} FprintManagerPrivate; } FprintManagerPrivate;
G_DEFINE_TYPE_WITH_CODE (FprintManager, fprint_manager, G_TYPE_OBJECT, G_ADD_PRIVATE (FprintManager)) G_DEFINE_TYPE_WITH_CODE (FprintManager, fprint_manager, G_TYPE_OBJECT, G_ADD_PRIVATE (FprintManager))
@ -60,6 +68,10 @@ fprint_manager_finalize (GObject *object)
{ {
FprintManagerPrivate *priv = fprint_manager_get_instance_private (FPRINT_MANAGER (object)); FprintManagerPrivate *priv = fprint_manager_get_instance_private (FPRINT_MANAGER (object));
if (priv->prepare_for_sleep_id)
g_dbus_connection_signal_unsubscribe (priv->connection,
priv->prepare_for_sleep_id);
g_clear_object (&priv->object_manager); g_clear_object (&priv->object_manager);
g_clear_object (&priv->dbus_manager); g_clear_object (&priv->dbus_manager);
g_clear_object (&priv->connection); g_clear_object (&priv->connection);
@ -152,14 +164,14 @@ fprint_manager_timeout_cb (FprintManager *manager)
} }
static void static void
fprint_manager_in_use_notified (FprintDevice *rdev, GParamSpec *spec, FprintManager *manager) fprint_manager_busy_notified (FprintDevice *rdev, GParamSpec *spec, FprintManager *manager)
{ {
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager); FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
guint num_devices_used = 0; guint num_devices_busy = 0;
g_autolist (GDBusObject) devices = NULL; g_autolist (GDBusObject) devices = NULL;
GList *l; GList *l;
gboolean in_use; gboolean busy;
if (priv->timeout_id > 0) if (priv->timeout_id > 0)
{ {
@ -177,12 +189,12 @@ fprint_manager_in_use_notified (FprintDevice *rdev, GParamSpec *spec, FprintMana
FprintDBusObjectSkeleton *object = l->data; FprintDBusObjectSkeleton *object = l->data;
dev = fprint_dbus_object_skeleton_get_device (object); dev = fprint_dbus_object_skeleton_get_device (object);
g_object_get (G_OBJECT (dev), "in-use", &in_use, NULL); g_object_get (G_OBJECT (dev), "busy", &busy, NULL);
if (in_use != FALSE) if (busy != FALSE)
num_devices_used++; num_devices_busy++;
} }
if (num_devices_used == 0) if (num_devices_busy == 0)
priv->timeout_id = g_timeout_add_seconds (TIMEOUT, (GSourceFunc) fprint_manager_timeout_cb, manager); priv->timeout_id = g_timeout_add_seconds (TIMEOUT, (GSourceFunc) fprint_manager_timeout_cb, manager);
} }
@ -227,6 +239,153 @@ handle_get_default_device (FprintManager *manager,
return TRUE; return TRUE;
} }
static void
fprint_device_suspend_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GError) error = NULL;
FprintManager *manager = FPRINT_MANAGER (user_data);
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
/* Fetch the result (except for the NULL dummy call). */
if (source_object != NULL)
{
fprint_device_suspend_finish (FPRINT_DEVICE (source_object), res, &error);
if (error)
{
if (!g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_NOT_OPEN) &&
!g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_NOT_SUPPORTED))
g_message ("Unexpected error while suspending device: %s", error->message);
}
}
priv->prepare_for_sleep_pending -= 1;
/* Close FD when all devices are prepared for sleeping. */
if (priv->prepare_for_sleep_pending == 0)
{
if (priv->sleep_inhibit_fd >= 0)
close (priv->sleep_inhibit_fd);
priv->sleep_inhibit_fd = -1;
g_debug ("Released delay inhibitor for sleep.");
}
g_object_unref (manager);
}
static void
logind_sleep_inhibit_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GVariant) data = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GUnixFDList) out_fd_list = NULL;
g_autoptr(FprintManager) manager = FPRINT_MANAGER (user_data);
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
gint fd_offset;
data = g_dbus_connection_call_with_unix_fd_list_finish (priv->connection, &out_fd_list, res, &error);
if (!data)
{
g_warning ("Failed to install a sleep delay inhibitor: %s", error->message);
return;
}
if (priv->sleep_inhibit_fd >= 0)
close (priv->sleep_inhibit_fd);
g_debug ("Got delay inhibitor for sleep.");
g_variant_get (data, "(h)", &fd_offset);
priv->sleep_inhibit_fd = g_unix_fd_list_get (out_fd_list, fd_offset, NULL);
}
static void
handle_prepare_for_sleep_signal (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
g_autolist (GDBusObject) devices = NULL;
FprintManager *manager = FPRINT_MANAGER (user_data);
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
gboolean prepare_for_sleep;
GList *l;
if (!g_variant_check_format_string (parameters, "(b)", FALSE))
{
g_warning ("Received incorrect parameter for PrepareForSleep signal");
return;
}
g_variant_get (parameters, "(b)", &prepare_for_sleep);
/* called one more time to handle the case of no devices */
if (prepare_for_sleep)
priv->prepare_for_sleep_pending = 1;
devices = g_dbus_object_manager_get_objects (priv->object_manager);
g_debug ("Preparing devices for %s", prepare_for_sleep ? "sleep" : "resume");
for (l = devices; l != NULL; l = l->next)
{
g_autoptr(FprintDevice) dev = NULL;
FprintDBusObjectSkeleton *object = l->data;
dev = fprint_dbus_object_skeleton_get_device (object);
if (prepare_for_sleep)
{
priv->prepare_for_sleep_pending += 1;
g_object_ref (manager);
fprint_device_suspend (dev, fprint_device_suspend_cb, manager);
}
else
{
fprint_device_resume (dev, NULL, NULL);
}
}
if (prepare_for_sleep)
{
/* "Notify" the initial dummy device we added, handling no devices that suspending */
g_object_ref (manager);
fprint_device_suspend_cb (NULL, NULL, manager);
}
else
{
GVariant *arg = NULL;
arg = g_variant_new ("(ssss)",
"sleep",
"net.reactivated.Fprint",
"Suspend fingerprint readers",
"delay");
/* Grab a sleep inhibitor. */
g_dbus_connection_call_with_unix_fd_list (priv->connection,
LOGIND_BUS_NAME,
LOGIND_OBJ_PATH,
LOGIND_IFACE_NAME,
"Inhibit",
arg,
G_VARIANT_TYPE ("(h)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
NULL,
logind_sleep_inhibit_cb,
g_object_ref (manager));
}
}
static void static void
device_added_cb (FprintManager *manager, FpDevice *device, FpContext *context) device_added_cb (FprintManager *manager, FpDevice *device, FpContext *context)
{ {
@ -238,8 +397,8 @@ device_added_cb (FprintManager *manager, FpDevice *device, FpContext *context)
rdev = fprint_device_new (device); rdev = fprint_device_new (device);
g_signal_connect (G_OBJECT (rdev), "notify::in-use", g_signal_connect (G_OBJECT (rdev), "notify::busy",
G_CALLBACK (fprint_manager_in_use_notified), manager); G_CALLBACK (fprint_manager_busy_notified), manager);
path = get_device_path (rdev); path = get_device_path (rdev);
@ -282,14 +441,15 @@ device_removed_cb (FprintManager *manager, FpDevice *device, FpContext *context)
break; break;
} }
/* The device that disappeared might have been in-use. /* The device that disappeared might have been busy.
* Do we need to do anything else in this case to clean up more gracefully? */ * Do we need to do anything else in this case to clean up more gracefully? */
fprint_manager_in_use_notified (NULL, NULL, manager); fprint_manager_busy_notified (NULL, NULL, manager);
} }
static void static void
fprint_manager_constructed (GObject *object) fprint_manager_constructed (GObject *object)
{ {
g_autoptr(GVariant) param_false = NULL;
FprintManager *manager = FPRINT_MANAGER (object); FprintManager *manager = FPRINT_MANAGER (object);
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager); FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
GDBusObjectManagerServer *object_manager_server; GDBusObjectManagerServer *object_manager_server;
@ -319,6 +479,20 @@ fprint_manager_constructed (GObject *object)
g_dbus_object_manager_server_set_connection (object_manager_server, g_dbus_object_manager_server_set_connection (object_manager_server,
priv->connection); priv->connection);
priv->prepare_for_sleep_id = g_dbus_connection_signal_subscribe (priv->connection,
LOGIND_BUS_NAME,
LOGIND_IFACE_NAME,
"PrepareForSleep",
LOGIND_OBJ_PATH,
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
handle_prepare_for_sleep_signal,
manager,
NULL);
/* Fake a resume as that triggers the inhibitor to be taken. */
param_false = g_variant_new ("(b)", FALSE);
handle_prepare_for_sleep_signal (priv->connection, NULL, NULL, NULL, NULL, param_false, manager);
/* And register the signals for initial enumeration and hotplug. */ /* And register the signals for initial enumeration and hotplug. */
g_signal_connect_object (priv->context, g_signal_connect_object (priv->context,
"device-added", "device-added",

View File

@ -38,6 +38,7 @@ gi.require_version('FPrint', '2.0')
from gi.repository import GLib, Gio, FPrint from gi.repository import GLib, Gio, FPrint
from output_checker import OutputChecker from output_checker import OutputChecker
import cairo import cairo
import signal
try: try:
from subprocess import DEVNULL from subprocess import DEVNULL
@ -120,6 +121,8 @@ class Connection:
self.con.close() self.con.close()
del self.con del self.con
# Speed up tests by only loading a 128x128px area from the center
MAX_IMG_SIZE = 128
def load_image(img): def load_image(img):
png = cairo.ImageSurface.create_from_png(img) png = cairo.ImageSurface.create_from_png(img)
@ -128,7 +131,13 @@ def load_image(img):
h = png.get_height() h = png.get_height()
w = (w + 3) // 4 * 4 w = (w + 3) // 4 * 4
h = (h + 3) // 4 * 4 h = (h + 3) // 4 * 4
img = cairo.ImageSurface(cairo.Format.A8, w, h)
w_out = min(MAX_IMG_SIZE, w)
h_out = min(MAX_IMG_SIZE, h)
x = (w - w_out) // 2
y = (h - h_out) // 2
img = cairo.ImageSurface(cairo.Format.A8, w_out, h_out)
cr = cairo.Context(img) cr = cairo.Context(img)
cr.set_source_rgba(1, 1, 1, 1) cr.set_source_rgba(1, 1, 1, 1)
@ -137,7 +146,7 @@ def load_image(img):
cr.set_source_rgba(0, 0, 0, 0) cr.set_source_rgba(0, 0, 0, 0)
cr.set_operator(cairo.OPERATOR_SOURCE) cr.set_operator(cairo.OPERATOR_SOURCE)
cr.set_source_surface(png) cr.set_source_surface(png, -x, -y)
cr.paint() cr.paint()
return img return img
@ -164,6 +173,11 @@ class FPrintdTest(dbusmock.DBusTestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
# Try to generate backtrace if meson kills as with SIGTERM
def r(*args):
raise KeyboardInterrupt()
signal.signal(signal.SIGTERM, r)
super().setUpClass() super().setUpClass()
fprintd = None fprintd = None
cls._polkitd = None cls._polkitd = None
@ -233,10 +247,15 @@ class FPrintdTest(dbusmock.DBusTestCase):
argv.insert(2, '--suppressions=%s' % valgrind) argv.insert(2, '--suppressions=%s' % valgrind)
self.valgrind = True self.valgrind = True
self.kill_daemon = False self.kill_daemon = False
self.daemon_log = OutputChecker()
self.daemon = subprocess.Popen(argv, self.daemon = subprocess.Popen(argv,
env=env, env=env,
stdout=None, stdout=self.daemon_log.fd,
stderr=subprocess.STDOUT) stderr=subprocess.STDOUT)
self.daemon_log.writer_attached()
#subprocess.Popen(['/usr/bin/dbus-monitor', '--system'])
self.addCleanup(self.daemon_stop) self.addCleanup(self.daemon_stop)
timeout_count = timeout * 10 timeout_count = timeout * 10
@ -296,6 +315,8 @@ class FPrintdTest(dbusmock.DBusTestCase):
else: else:
raise(e) raise(e)
self.daemon_log.assert_closed()
if not self.kill_daemon: if not self.kill_daemon:
self.assertLess(self.daemon.returncode, 128) self.assertLess(self.daemon.returncode, 128)
self.assertGreaterEqual(self.daemon.returncode, 0) self.assertGreaterEqual(self.daemon.returncode, 0)
@ -577,8 +598,22 @@ class FPrintdVirtualDeviceBaseTest(FPrintdVirtualImageDeviceBaseTests):
self.manager = None self.manager = None
self.device = None self.device = None
self.polkitd_start() self.polkitd_start()
fifo_path = os.path.join(self.tmpdir, 'logind_inhibit_fifo')
os.mkfifo(fifo_path)
self.logind_inhibit_fifo = os.open(fifo_path, os.O_RDONLY | os.O_NONBLOCK | os.O_CLOEXEC)
# EOF without a writer, BlockingIOError with a writer
self.assertFalse(self.holds_inhibitor())
self.logind, self.logind_obj = self.spawn_server_template('logind', { })
self.logind_obj.AddMethod('org.freedesktop.login1.Manager', 'Inhibit', 'ssss', 'h',
'ret = os.open("%s", os.O_WRONLY)\n' % fifo_path +
'from gi.repository import GLib\n' +
'GLib.idle_add(lambda fd: os.close(fd), ret)')
self.daemon_start(self.driver_name) self.daemon_start(self.driver_name)
self.wait_got_delay_inhibitor()
if self.device is None: if self.device is None:
self.skipTest("Need {} device to run the test".format(self.device_driver)) self.skipTest("Need {} device to run the test".format(self.device_driver))
@ -627,6 +662,8 @@ class FPrintdVirtualDeviceBaseTest(FPrintdVirtualImageDeviceBaseTests):
self.device = None self.device = None
self.manager = None self.manager = None
os.close(self.logind_inhibit_fifo)
super().tearDown() super().tearDown()
def try_release(self): def try_release(self):
@ -658,6 +695,23 @@ class FPrintdVirtualDeviceBaseTest(FPrintdVirtualImageDeviceBaseTests):
if expected is not None: if expected is not None:
self.assertEqual(self._last_result, expected) self.assertEqual(self._last_result, expected)
def holds_inhibitor(self):
try:
if os.read(self.logind_inhibit_fifo, 1) == b'':
return False
except BlockingIOError:
return True
raise AssertionError("logind inhibitor fifo in unexpected state")
def wait_got_delay_inhibitor(self, timeout=0):
self.daemon_log.check_line('Got delay inhibitor for sleep', timeout=timeout)
self.assertTrue(self.holds_inhibitor())
def wait_released_delay_inhibitor(self, timeout=0):
self.daemon_log.check_line('Released delay inhibitor for sleep', timeout=timeout)
self.assertFalse(self.holds_inhibitor())
def enroll_image(self, img, device=None, finger='right-index-finger', def enroll_image(self, img, device=None, finger='right-index-finger',
expected_result='enroll-completed', claim_user=None, expected_result='enroll-completed', claim_user=None,
start=True, stop=True): start=True, stop=True):
@ -1032,6 +1086,51 @@ class FPrintdVirtualStorageDeviceTests(FPrintdVirtualStorageDeviceBaseTest):
prints = self.get_stored_prints() prints = self.get_stored_prints()
self.assertEqual(set(prints), set(garbage_prints)) self.assertEqual(set(prints), set(garbage_prints))
def test_local_storage_cleanup_data_error(self):
# Enroll a print and delete it
self.enroll_print('deleted-print', finger='left-thumb')
self.send_command('REMOVE', 'deleted-print')
# Note: would be thrown anyway by the storage device if we scan something
self.send_error(FPrint.DeviceError.DATA_NOT_FOUND)
self.device.VerifyStart('(s)', 'any')
self.wait_for_result('verify-no-match')
self.device.VerifyStop()
# At this point, there is no print left
with self.assertFprintError('NoEnrolledPrints'):
self.device.ListEnrolledFingers('(s)', 'testuser')
def test_local_storage_cleanup_no_match(self):
# Enroll a print and delete it
self.enroll_print('existing-print', finger='right-index-finger')
self.enroll_print('deleted-print', finger='left-thumb')
self.send_command('REMOVE', 'deleted-print')
# We need to send a print that is known to the device
self.send_image('other-print')
self.device.VerifyStart('(s)', 'right-index-finger')
self.wait_for_result('verify-no-match')
self.device.VerifyStop()
# At this point, the deleted print has disappeared
self.assertEqual(set(self.device.ListEnrolledFingers('(s)', 'testuser')), {'right-index-finger'})
# Now, do the same thing, and the print will not be deleted
self.enroll_print('deleted-print', finger='left-thumb')
self.send_command('REMOVE', 'deleted-print')
self.send_image('other-print')
self.device.VerifyStart('(s)', 'right-index-finger')
self.wait_for_result('verify-no-match')
self.device.VerifyStop()
# At this point, the deleted print is still there
self.assertEqual(set(self.device.ListEnrolledFingers('(s)', 'testuser')), {'right-index-finger', 'left-thumb'})
def test_enroll_with_one_stage_only(self): def test_enroll_with_one_stage_only(self):
self._maybe_reduce_enroll_stages(stages=1) self._maybe_reduce_enroll_stages(stages=1)
@ -1524,6 +1623,72 @@ class FPrintdVirtualDeviceTest(FPrintdVirtualDeviceBaseTest):
self.assertIn(GLib.Variant('()', ()), self.get_all_async_replies()) self.assertIn(GLib.Variant('()', ()), self.get_all_async_replies())
def test_suspend_inhibit_unclaimed(self):
self.logind_obj.EmitSignal("", "PrepareForSleep", "b", [True])
self.daemon_log.check_line('Preparing devices for sleep', timeout=1)
self.wait_released_delay_inhibitor(timeout=1)
self.logind_obj.EmitSignal("", "PrepareForSleep", "b", [False])
self.daemon_log.check_line('Preparing devices for resume', timeout=1)
self.wait_got_delay_inhibitor(timeout=1)
def test_suspend_inhibit_claimed(self):
self.device.Claim('(s)', 'testuser')
self.logind_obj.EmitSignal("", "PrepareForSleep", "b", [True])
self.daemon_log.check_line('Preparing devices for sleep', timeout=1)
self.wait_released_delay_inhibitor(timeout=1)
self.logind_obj.EmitSignal("", "PrepareForSleep", "b", [False])
self.daemon_log.check_line('Preparing devices for resume', timeout=1)
self.wait_got_delay_inhibitor(timeout=1)
self.device.Release()
def test_suspend_inhibit_cancels_enroll(self):
self.device.Claim('(s)', 'testuser')
self.device.EnrollStart('(s)', 'right-thumb')
# Now prepare for sleep, which will trigger an internal cancellation
self.logind_obj.EmitSignal("", "PrepareForSleep", "b", [True])
self.daemon_log.check_line('Preparing devices for sleep', timeout=1)
self.wait_for_result(expected='enroll-unknown-error')
self.wait_released_delay_inhibitor(timeout=1)
self.assertEqual(os.read(self.logind_inhibit_fifo, 1), b'')
self.logind_obj.EmitSignal("", "PrepareForSleep", "b", [False])
self.daemon_log.check_line('Preparing devices for resume', timeout=1)
self.wait_got_delay_inhibitor(timeout=1)
self.device.Release()
def test_suspend_prevents_enroll(self):
self.device.Claim('(s)', 'testuser')
# Now prepare for sleep, which will trigger an internal cancellation
self.logind_obj.EmitSignal("", "PrepareForSleep", "b", [True])
self.daemon_log.check_line('Preparing devices for sleep', timeout=1)
self.wait_released_delay_inhibitor(timeout=1)
self.device.EnrollStart('(s)', 'right-thumb')
self.wait_for_result(expected='enroll-unknown-error')
self.logind_obj.EmitSignal("", "PrepareForSleep", "b", [False])
self.daemon_log.check_line('Preparing devices for resume', timeout=1)
self.wait_got_delay_inhibitor(timeout=1)
self.device.Release()
class FPrintdVirtualDeviceStorageTest(FPrintdVirtualStorageDeviceBaseTest, class FPrintdVirtualDeviceStorageTest(FPrintdVirtualStorageDeviceBaseTest,
FPrintdVirtualDeviceTest): FPrintdVirtualDeviceTest):
@ -2580,7 +2745,7 @@ class FPrintdVirtualDeviceVerificationTests(FPrintdVirtualDeviceBaseTest):
self.assertVerifyError(FPrint.DeviceError.DATA_INVALID, 'verify-unknown-error') self.assertVerifyError(FPrint.DeviceError.DATA_INVALID, 'verify-unknown-error')
def test_verify_error_data_not_found(self): def test_verify_error_data_not_found(self):
self.assertVerifyError(FPrint.DeviceError.DATA_NOT_FOUND, 'verify-unknown-error') self.assertVerifyError(FPrint.DeviceError.DATA_NOT_FOUND, 'verify-no-match')
def test_verify_error_data_full(self): def test_verify_error_data_full(self):
self.assertVerifyError(FPrint.DeviceError.DATA_FULL, 'verify-unknown-error') self.assertVerifyError(FPrint.DeviceError.DATA_FULL, 'verify-unknown-error')
@ -2665,15 +2830,6 @@ class FPrintdVirtualDeviceVerificationTests(FPrintdVirtualDeviceBaseTest):
self.assertIsNone(self._last_result) self.assertIsNone(self._last_result)
self.assertFalse(self.finger_present) self.assertFalse(self.finger_present)
def test_verify_stop_restarts_immediately(self):
self.send_image('tented_arch')
self.assertVerifyNoMatch()
self.call_device_method_async('VerifyStop', '()', [])
self.call_device_method_async('VerifyStart', '(s)', [self.verify_finger])
self.wait_for_device_reply(expected_replies=2)
def test_verify_stop_waits_for_completion(self): def test_verify_stop_waits_for_completion(self):
self.stop_on_teardown = False self.stop_on_teardown = False

View File

@ -43,25 +43,34 @@ class OutputChecker(object):
fcntl.fcntl(self._pipe_fd_w, fcntl.F_GETFL) | os.O_CLOEXEC) fcntl.fcntl(self._pipe_fd_w, fcntl.F_GETFL) | os.O_CLOEXEC)
# Start copier thread # Start copier thread
self._thread = threading.Thread(target=self._copy) self._thread = threading.Thread(target=self._copy, daemon=True)
self._thread.start() self._thread.start()
def _copy(self): def _copy(self):
p = select.poll()
p.register(self._pipe_fd_r)
while True: while True:
try: try:
# Be lazy and wake up occasionally in case _pipe_fd_r became invalid # Be lazy and wake up occasionally in case _pipe_fd_r became invalid
# The reason to do this is because os.read() will *not* return if the # The reason to do this is because os.read() will *not* return if the
# FD is forcefully closed. # FD is forcefully closed.
select.select([self._pipe_fd_r], [], [], 0.1) p.poll(0.1)
r = os.read(self._pipe_fd_r, 1024) r = os.read(self._pipe_fd_r, 1024)
if not r: if not r:
os.close(self._pipe_fd_r)
self._pipe_fd_r = -1
self._lines_sem.release()
return return
except OSError as e: except OSError as e:
if e.errno == errno.EWOULDBLOCK: if e.errno == errno.EWOULDBLOCK:
continue continue
# We get a bad file descriptor error when the outside closes the FD # We get a bad file descriptor error when the outside closes the FD
if self._pipe_fd_r >= 0:
os.close(self._pipe_fd_r)
self._pipe_fd_r = -1
self._lines_sem.release()
return return
l = r.split(b'\n') l = r.split(b'\n')
@ -86,6 +95,13 @@ class OutputChecker(object):
try: try:
l = self._lines.pop(0) l = self._lines.pop(0)
except IndexError: except IndexError:
# EOF, throw error
if self._pipe_fd_r == -1:
if failmsg:
raise AssertionError("No further messages: " % failmsg)
else:
raise AssertionError('No client waiting for needle %s' % (str(needle_re)))
# Check if should wake up # Check if should wake up
if not self._lines_sem.acquire(timeout = deadline - time.time()): if not self._lines_sem.acquire(timeout = deadline - time.time()):
if failmsg: if failmsg:
@ -119,6 +135,10 @@ class OutputChecker(object):
try: try:
l = self._lines.pop(0) l = self._lines.pop(0)
except IndexError: except IndexError:
# EOF, so everything good
if self._pipe_fd_r == -1:
break
# Check if should wake up # Check if should wake up
if not self._lines_sem.acquire(timeout = deadline - time.time()): if not self._lines_sem.acquire(timeout = deadline - time.time()):
# Timed out, so everything is good # Timed out, so everything is good
@ -130,7 +150,7 @@ class OutputChecker(object):
if failmsg: if failmsg:
raise AssertionError(failmsg) raise AssertionError(failmsg)
else: else:
raise AssertionError('Found needle %s but shouldn\'t have been there (timeout: %0.2f)' % (str(needle_re), timeout)) raise AssertionError('Found needle %s but shouldn\'t have been there (timeout: %0.2f)' % (str(needle_re), wait))
return ret return ret
@ -157,6 +177,7 @@ class OutputChecker(object):
fd = self._pipe_fd_r fd = self._pipe_fd_r
self._pipe_fd_r = -1 self._pipe_fd_r = -1
if fd >= 0:
os.close(fd) os.close(fd)
self._thread.join() self._thread.join()
@ -170,9 +191,9 @@ class OutputChecker(object):
self._pipe_fd_w = -1 self._pipe_fd_w = -1
def __del__(self): def __del__(self):
if self._pipe_fd_r > 0: if self._pipe_fd_r >= 0:
os.close(self._pipe_fd_r) os.close(self._pipe_fd_r)
if self._pipe_fd_w > 0: self._pipe_fd_r = -1
if self._pipe_fd_w >= 0:
os.close(self._pipe_fd_w) os.close(self._pipe_fd_w)
self._pipe_fd_w = -1
assert not self._thread.is_alive()

View File

@ -143,6 +143,12 @@ class TestPamFprintd(dbusmock.DBusTestCase):
self.assertRegex(res.info[0], r'Swipe your left little finger across the fingerprint reader') self.assertRegex(res.info[0], r'Swipe your left little finger across the fingerprint reader')
self.assertEqual(len(res.errors), 0) self.assertEqual(len(res.errors), 0)
# Check that we can stop verification and release the device. i.e.
# this has not been done by PAM already (the real fprintd would notice
# the disconnect, the mock service does not).
self.device_mock.VerifyStop()
self.device_mock.Release()
def test_pam_fprintd_no_fingers(self): def test_pam_fprintd_no_fingers(self):
self.setup_device() self.setup_device()
self.device_mock.SetEnrolledFingers('toto', dbus.Array(set([]), signature='s')) self.device_mock.SetEnrolledFingers('toto', dbus.Array(set([]), signature='s'))
@ -199,6 +205,13 @@ class TestPamFprintd(dbusmock.DBusTestCase):
self.assertRegex(res.errors[0], r'Failed to match fingerprint') self.assertRegex(res.errors[0], r'Failed to match fingerprint')
self.assertRegex(res.errors[0], r'Failed to match fingerprint') self.assertRegex(res.errors[0], r'Failed to match fingerprint')
# Check that we can cannot stop verification or release the device. i.e.
# PAM should have correctly done this after verification was done.
with self.assertRaisesRegex(dbus.exceptions.DBusException, r'net\.reactivated\.Fprint\.Error\.NoActionInProgress'):
self.device_mock.VerifyStop()
with self.assertRaisesRegex(dbus.exceptions.DBusException, r'net\.reactivated\.Fprint\.Error\.ClaimDevice'):
self.device_mock.Release()
def test_pam_fprintd_blocks_unexpected_auth2(self): def test_pam_fprintd_blocks_unexpected_auth2(self):
self.setup_device() self.setup_device()
script = [ script = [

View File

@ -1,9 +0,0 @@
#!/bin/sh
test -f .tx/config || exit 1
echo Pulling translations from Transifex
tx --root `dirname $0` pull --all --force --skip
echo Pushing strings to Transifex
tx push --source