[systemd-commits] 9 commits - configure.ac .gitignore Makefile.am Makefile-man.am man/systemd-fsckd.service.xml man/systemd-fsck at .service.xml po/de.po po/el.po po/fr.po po/hu.po po/it.po po/pl.po po/POTFILES.in po/pt_BR.po po/ru.po po/sv.po po/uk.po src/fsck src/fsckd src/shared test/mocks units/.gitignore units/systemd-fsckd.service.in units/systemd-fsckd.socket units/systemd-fsck-root.service.in units/systemd-fsck at .service.in

Martin Pitt martin at kemper.freedesktop.org
Wed Feb 18 07:47:27 PST 2015


 .gitignore                         |    1 
 Makefile-man.am                    |   12 
 Makefile.am                        |   16 +
 configure.ac                       |    1 
 man/systemd-fsck at .service.xml      |   26 -
 man/systemd-fsckd.service.xml      |  162 ++++++++++
 po/POTFILES.in                     |    1 
 po/de.po                           |   11 
 po/el.po                           |   11 
 po/fr.po                           |   11 
 po/hu.po                           |   11 
 po/it.po                           |   11 
 po/pl.po                           |   11 
 po/pt_BR.po                        |   11 
 po/ru.po                           |   11 
 po/sv.po                           |   11 
 po/uk.po                           |   12 
 src/fsck/fsck.c                    |  125 +++-----
 src/fsckd/Makefile                 |    1 
 src/fsckd/fsckd.c                  |  554 +++++++++++++++++++++++++++++++++++++
 src/fsckd/fsckd.h                  |   38 ++
 src/shared/util.c                  |    8 
 src/shared/util.h                  |    2 
 test/mocks/fsck                    |   27 +
 units/.gitignore                   |    1 
 units/systemd-fsck-root.service.in |    3 
 units/systemd-fsck at .service.in     |    4 
 units/systemd-fsckd.service.in     |   17 +
 units/systemd-fsckd.socket         |   14 
 29 files changed, 1038 insertions(+), 86 deletions(-)

New commits:
commit 89ea179b603cecfd1096a673073325f13028c421
Author: Didier Roche <didrocks at ubuntu.com>
Date:   Mon Jan 26 17:46:36 2015 +0100

    Add mock fsck process

diff --git a/test/mocks/fsck b/test/mocks/fsck
new file mode 100755
index 0000000..77b50d7
--- /dev/null
+++ b/test/mocks/fsck
@@ -0,0 +1,27 @@
+#!/bin/bash
+fd=0
+
+OPTIND=1
+while getopts "C:aTlM" opt; do
+    case "$opt" in
+        C)
+            fd=$OPTARG
+            ;;
+        \?);;
+    esac
+done
+
+shift "$((OPTIND-1))"
+device=$1
+
+echo "Running fake fsck on $device"
+
+declare -a maxpass=(30 5 2 30 60)
+
+for pass in {1..5}; do
+    maxprogress=${maxpass[$((pass-1))]}
+    for (( current=0; current<=${maxprogress}; current++)); do
+        echo "$pass $current $maxprogress $device">&$fd
+        sleep 0.1
+    done
+done

commit a80170f55c70f98c8bde663bd28046e48b258a01
Author: Didier Roche <didrocks at ubuntu.com>
Date:   Mon Jan 26 17:34:59 2015 +0100

    Add man page and references to it.
    
    Add man page explaining the plymouth theme protocol, usage of the daemon
    as well as the socket activation part.
    Adapt existing fsck man page.

diff --git a/Makefile-man.am b/Makefile-man.am
index d0fb9aa..7a9612e 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -66,6 +66,7 @@ MANPAGES += \
 	man/systemd-efi-boot-generator.8 \
 	man/systemd-escape.1 \
 	man/systemd-fsck at .service.8 \
+	man/systemd-fsckd.service.8 \
 	man/systemd-fstab-generator.8 \
 	man/systemd-getty-generator.8 \
 	man/systemd-gpt-auto-generator.8 \
@@ -209,6 +210,8 @@ MANPAGES_ALIAS += \
 	man/systemd-ask-password-wall.service.8 \
 	man/systemd-fsck-root.service.8 \
 	man/systemd-fsck.8 \
+	man/systemd-fsckd.8 \
+	man/systemd-fsckd.socket.8 \
 	man/systemd-hibernate-resume.8 \
 	man/systemd-hibernate.service.8 \
 	man/systemd-hybrid-sleep.service.8 \
@@ -321,6 +324,8 @@ man/systemd-ask-password-wall.path.8: man/systemd-ask-password-console.service.8
 man/systemd-ask-password-wall.service.8: man/systemd-ask-password-console.service.8
 man/systemd-fsck-root.service.8: man/systemd-fsck at .service.8
 man/systemd-fsck.8: man/systemd-fsck at .service.8
+man/systemd-fsckd.8: man/systemd-fsckd.service.8
+man/systemd-fsckd.socket.8: man/systemd-fsckd.service.8
 man/systemd-hibernate-resume.8: man/systemd-hibernate-resume at .service.8
 man/systemd-hibernate.service.8: man/systemd-suspend.service.8
 man/systemd-hybrid-sleep.service.8: man/systemd-suspend.service.8
@@ -601,6 +606,12 @@ man/systemd-fsck-root.service.html: man/systemd-fsck at .service.html
 man/systemd-fsck.html: man/systemd-fsck at .service.html
 	$(html-alias)
 
+man/systemd-fsckd.html: man/systemd-fsckd.service.html
+	$(html-alias)
+
+man/systemd-fsckd.socket.html: man/systemd-fsckd.service.html
+	$(html-alias)
+
 man/systemd-hibernate-resume.html: man/systemd-hibernate-resume at .service.html
 	$(html-alias)
 
@@ -1738,6 +1749,7 @@ EXTRA_DIST += \
 	man/systemd-escape.xml \
 	man/systemd-firstboot.xml \
 	man/systemd-fsck at .service.xml \
+	man/systemd-fsckd.service.xml \
 	man/systemd-fstab-generator.xml \
 	man/systemd-getty-generator.xml \
 	man/systemd-gpt-auto-generator.xml \
diff --git a/man/systemd-fsck at .service.xml b/man/systemd-fsck at .service.xml
index 88e11e8..69b8fdd 100644
--- a/man/systemd-fsck at .service.xml
+++ b/man/systemd-fsck at .service.xml
@@ -81,10 +81,10 @@
     last check, number of mounts, unclean unmount, etc.</para>
 
     <para><filename>systemd-fsck</filename> will forward file system
-    checking progress to the console. If a file system check fails for
-    a service without <option>nofail</option>, emergency mode is
-    activated, by isolating to
-    <filename>emergency.target</filename>.</para>
+    checking progress to <filename>systemd-fsckd.service</filename>
+    socket. If a file system check fails for a service without
+    <option>nofail</option>, emergency mode is activated, by isolating
+    to <filename>emergency.target</filename>.</para>
   </refsect1>
 
   <refsect1>
@@ -125,16 +125,16 @@
     <title>See Also</title>
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>fsck</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-quotacheck.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>fsck.btrfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>fsck.cramfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>fsck.ext4</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>fsck.fat</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>fsck.hfsplus</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>fsck.minix</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>fsck.ntfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>fsck.xfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+      <citerefentry project='man-pages'><refentrytitle>fsck.btrfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.cramfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.ext4</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.fat</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.hfsplus</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.minix</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.ntfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.xfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
     </para>
   </refsect1>
 
diff --git a/man/systemd-fsckd.service.xml b/man/systemd-fsckd.service.xml
new file mode 100644
index 0000000..2ad7844
--- /dev/null
+++ b/man/systemd-fsckd.service.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0"?>
+<!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!--
+  This file is part of systemd.
+
+  Copyright 2015 Canonical
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+<refentry id="systemd-fsckd.service" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>systemd-fsckd.service</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Didier</firstname>
+        <surname>Roche</surname>
+        <email>didrocks at ubuntu.com</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>systemd-fsckd.service</refentrytitle>
+    <manvolnum>8</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>systemd-fsckd.service</refname>
+    <refname>systemd-fsckd.socket</refname>
+    <refname>systemd-fsckd</refname>
+    <refpurpose>File system check progress reporting</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <para><filename>systemd-fsckd.service</filename></para>
+    <para><filename>systemd-fsckd.socket</filename></para>
+    <para><filename>/usr/lib/systemd/systemd-fsckd</filename></para>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><filename>systemd-fsckd.service</filename> is a service responsible
+    for receiving file system check progress, and communicating some
+    consolidated data to console and plymouth (if running). It also handles
+    possible check cancellations.</para>
+
+    <para><command>systemd-fsckd</command> receives messages about file
+    system check progress from <command>systemd-fsck</command> through a
+    UNIX domain socket. It can display the progress of the least advanced
+    fsck as well as the total number of devices being checked in parallel
+    to the console. It will also send progress messages to plymouth.
+    Both the raw data and translated messages are sent, so compiled
+    plymouth themes can use the raw data to display custom messages, and
+    scripted themes, not supporting i18n, can display the translated
+    versions.</para>
+
+    <para><command>systemd-fsckd</command> will instruct plymouth to grab
+    Control+C keypresses. When the key is pressed, running checks will be
+    terminated. It will also cancel any newly connected fsck instances for
+    the lifetime of <filename>systemd-fsckd</filename>.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Protocol for communication with plymouth</title>
+
+    <para><filename>systemd-fsckd</filename> passes the
+    following messages to the theme:</para>
+
+    <para>Progress update, sent as a plymouth update message:
+      <literal>fsckd:<num_devices>:<progress>:<string></literal>
+      <variablelist>
+        <varlistentry>
+          <term><literal><num_devices></literal></term>
+          <listitem><para>the current number of devices
+          being checked (int)</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><literal><progress></literal></term>
+          <listitem><para>the current minimum percentage of
+          all devices being checking (float, from 0 to 100)</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><literal><string></literal></term>
+          <listitem><para>a translated message ready to be displayed
+          by the plymouth theme displaying the data above. It can be overriden
+          by themes supporting i18n.</para></listitem>
+        </varlistentry>
+      </variablelist>
+    </para>
+
+    <para>Cancel message, sent as a traditional plymouth message:
+      <literal>fsckd-cancel-msg:<string></literal>
+      <variablelist>
+        <varlistentry>
+          <term><literal><strings></literal></term>
+          <listitem><para>a translated string ready to be displayed
+          by the plymouth theme indicating that Control+C can be used to cancel
+          current checks. It can be overriden (matching only
+          <literal>fsckd-cancel-msg</literal> prefix)
+          by themes supporting i18n.</para></listitem>
+        </varlistentry>
+      </variablelist>
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>Options</title>
+
+    <para>The following options are understood:</para>
+
+    <variablelist>
+      <xi:include href="standard-options.xml" xpointer="help" />
+      <xi:include href="standard-options.xml" xpointer="version" />
+    </variablelist>
+
+  </refsect1>
+
+  <refsect1>
+    <title>Exit status</title>
+
+    <para>On success, 0 is returned, a non-zero failure
+    code otherwise. Note that the daemon stays idle for
+    a while to accept new <filename>systemd-fsck</filename>
+    connections before exiting.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>See Also</title>
+    <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-fsck</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-quotacheck.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.btrfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.cramfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.ext4</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.fat</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.hfsplus</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.minix</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.ntfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>fsck.xfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
diff --git a/units/systemd-fsckd.service.in b/units/systemd-fsckd.service.in
index 27c325f..9c7ed51 100644
--- a/units/systemd-fsckd.service.in
+++ b/units/systemd-fsckd.service.in
@@ -7,6 +7,7 @@
 
 [Unit]
 Description=File System Check Daemon to report status
+Documentation=man:systemd-fsckd.service(8)
 DefaultDependencies=no
 Requires=systemd-fsckd.socket
 Before=shutdown.target
diff --git a/units/systemd-fsckd.socket b/units/systemd-fsckd.socket
index a8994a1..93c4ea9 100644
--- a/units/systemd-fsckd.socket
+++ b/units/systemd-fsckd.socket
@@ -7,7 +7,7 @@
 
 [Unit]
 Description=fsck to fsckd communication Socket
-Documentation=man:systemd-fsck at .service(8) man:systemd-fsck-root.service(8)
+Documentation=man:systemd-fsckd.service(8) man:systemd-fsck at .service(8) man:systemd-fsck-root.service(8)
 DefaultDependencies=no
 
 [Socket]

commit 66f2ff06ca4ee5ea686b884e2923a31832ad8fe4
Author: Didier Roche <didrocks at ubuntu.com>
Date:   Mon Jan 26 17:30:00 2015 +0100

    Add fsckd service and socket, retarget systemd-fsck
    
    systemd-fsckd can be socket-activated by systemd-fsck process. Reflect that
    in the different unit files.

diff --git a/Makefile.am b/Makefile.am
index a15b53b..d9d71df 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -494,6 +494,7 @@ dist_systemunit_DATA = \
 	units/slices.target \
 	units/system.slice \
 	units/x-.slice \
+	units/systemd-fsckd.socket \
 	units/systemd-initctl.socket \
 	units/systemd-shutdownd.socket \
 	units/syslog.socket \
@@ -545,6 +546,7 @@ nodist_systemunit_DATA = \
 	units/systemd-kexec.service \
 	units/systemd-fsck at .service \
 	units/systemd-fsck-root.service \
+	units/systemd-fsckd.service \
 	units/systemd-machine-id-commit.service \
 	units/systemd-udevd.service \
 	units/systemd-udev-trigger.service \
@@ -598,6 +600,7 @@ EXTRA_DIST += \
 	units/user/systemd-exit.service.in \
 	units/systemd-fsck at .service.in \
 	units/systemd-fsck-root.service.in \
+	units/systemd-fsckd.service.in \
 	units/systemd-machine-id-commit.service.in \
 	units/user at .service.m4.in \
 	units/debug-shell.service.in \
diff --git a/units/.gitignore b/units/.gitignore
index 6fdb629..26ae965 100644
--- a/units/.gitignore
+++ b/units/.gitignore
@@ -28,6 +28,7 @@
 /systemd-firstboot.service
 /systemd-fsck-root.service
 /systemd-fsck at .service
+/systemd-fsckd.service
 /systemd-machine-id-commit.service
 /systemd-halt.service
 /systemd-hibernate.service
diff --git a/units/systemd-fsck-root.service.in b/units/systemd-fsck-root.service.in
index 6d76578..f493445 100644
--- a/units/systemd-fsck-root.service.in
+++ b/units/systemd-fsck-root.service.in
@@ -9,12 +9,13 @@
 Description=File System Check on Root Device
 Documentation=man:systemd-fsck-root.service(8)
 DefaultDependencies=no
+Wants=systemd-fsckd.socket
 Before=local-fs.target shutdown.target
+After=systemd-fsckd.socket
 ConditionPathIsReadWrite=!/
 
 [Service]
 Type=oneshot
 RemainAfterExit=yes
 ExecStart=@rootlibexecdir@/systemd-fsck
-StandardOutput=journal+console
 TimeoutSec=0
diff --git a/units/systemd-fsck at .service.in b/units/systemd-fsck at .service.in
index 857e625..e6d98c0 100644
--- a/units/systemd-fsck at .service.in
+++ b/units/systemd-fsck at .service.in
@@ -10,12 +10,12 @@ Description=File System Check on %f
 Documentation=man:systemd-fsck at .service(8)
 DefaultDependencies=no
 BindsTo=%i.device
-After=%i.device systemd-fsck-root.service local-fs-pre.target
+Wants=systemd-fsckd.socket
+After=%i.device systemd-fsck-root.service local-fs-pre.target systemd-fsckd.socket
 Before=shutdown.target
 
 [Service]
 Type=oneshot
 RemainAfterExit=yes
 ExecStart=@rootlibexecdir@/systemd-fsck %f
-StandardOutput=journal+console
 TimeoutSec=0
diff --git a/units/systemd-fsckd.service.in b/units/systemd-fsckd.service.in
new file mode 100644
index 0000000..27c325f
--- /dev/null
+++ b/units/systemd-fsckd.service.in
@@ -0,0 +1,16 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=File System Check Daemon to report status
+DefaultDependencies=no
+Requires=systemd-fsckd.socket
+Before=shutdown.target
+
+[Service]
+ExecStart=@rootlibexecdir@/systemd-fsckd
+StandardOutput=journal+console
diff --git a/units/systemd-fsckd.socket b/units/systemd-fsckd.socket
new file mode 100644
index 0000000..a8994a1
--- /dev/null
+++ b/units/systemd-fsckd.socket
@@ -0,0 +1,14 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=fsck to fsckd communication Socket
+Documentation=man:systemd-fsck at .service(8) man:systemd-fsck-root.service(8)
+DefaultDependencies=no
+
+[Socket]
+ListenStream=/run/systemd/fsckd

commit d5e41df6d7a8e1814dded5e55e2c5a497fcf24dc
Author: Didier Roche <didrocks at ubuntu.com>
Date:   Mon Jan 26 17:23:08 2015 +0100

    Refresh po files
    
    Also, add new plymouth fsckd translated strings in french.
    Refreshed with "make update-po".

diff --git a/po/de.po b/po/de.po
index 69c1fb9..0f87024 100644
--- a/po/de.po
+++ b/po/de.po
@@ -454,5 +454,16 @@ msgstr ""
 "Legitimierung ist zum Festlegen, ob Netzwerkzeitabgeich eingeschaltet sein "
 "soll, erforderlich."
 
+#: ../src/fsckd/fsckd.c:186
+msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+msgstr ""
+
+#: ../src/fsckd/fsckd.c:227
+#, c-format
+msgid "Checking in progress on %d disk (%3.1f%% complete)"
+msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+msgstr[0] ""
+msgstr[1] ""
+
 #~ msgid "Privileged system and service manager access"
 #~ msgstr "Privilegierter Zugriff auf die System- und Dienstverwaltung"
diff --git a/po/el.po b/po/el.po
index 8f7a0ed..14ee497 100644
--- a/po/el.po
+++ b/po/el.po
@@ -402,3 +402,14 @@ msgid "Authentication is required to access the system and service manager."
 msgstr ""
 "Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και "
 "υπηρεσιών."
+
+#: ../src/fsckd/fsckd.c:186
+msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+msgstr ""
+
+#: ../src/fsckd/fsckd.c:227
+#, c-format
+msgid "Checking in progress on %d disk (%3.1f%% complete)"
+msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+msgstr[0] ""
+msgstr[1] ""
diff --git a/po/fr.po b/po/fr.po
index 4d4fc6b..8e44e0c 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -433,3 +433,14 @@ msgid ""
 msgstr ""
 "Authentification requise pour activer ou désactiver la synchronisation de "
 "l'heure avec le réseau."
+
+#: ../src/fsckd/fsckd.c:186
+msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+msgstr "Appuyez sur Ctrl+C pour annuler toutes vérifications du système de fichier en cours"
+
+#: ../src/fsckd/fsckd.c:227
+#, c-format
+msgid "Checking in progress on %d disk (%3.1f%% complete)"
+msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+msgstr[0] "Vérification en cours sur %d disque (%3.1f%% complété)"
+msgstr[1] "Vérification en cours sur %d disques (%3.1f%% complété)"
diff --git a/po/hu.po b/po/hu.po
index a914b3c..308e03d 100644
--- a/po/hu.po
+++ b/po/hu.po
@@ -411,3 +411,14 @@ msgstr "A systemd állapotának újratöltése"
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
 msgid "Authentication is required to reload the systemd state."
 msgstr "Hitelesítés szükséges a systemd állapotának újratöltéséhez."
+
+#: ../src/fsckd/fsckd.c:186
+msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+msgstr ""
+
+#: ../src/fsckd/fsckd.c:227
+#, c-format
+msgid "Checking in progress on %d disk (%3.1f%% complete)"
+msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+msgstr[0] ""
+msgstr[1] ""
diff --git a/po/it.po b/po/it.po
index 93a1e79..53cccfe 100644
--- a/po/it.po
+++ b/po/it.po
@@ -424,3 +424,14 @@ msgstr "Autenticazione richiesta per riavviare lo stato di sistemd."
 
 #~ msgid "Privileged system and service manager access"
 #~ msgstr "Accesso privilegiato per la gestione del sistema e dei servizi"
+
+#: ../src/fsckd/fsckd.c:186
+msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+msgstr ""
+
+#: ../src/fsckd/fsckd.c:227
+#, c-format
+msgid "Checking in progress on %d disk (%3.1f%% complete)"
+msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+msgstr[0] ""
+msgstr[1] ""
diff --git a/po/pl.po b/po/pl.po
index e5987be..cd7dbda 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -411,3 +411,14 @@ msgid ""
 msgstr ""
 "Wymagane jest uwierzytelnienie, aby kontrolować, czy włączyć synchronizację "
 "czasu przez sieć."
+
+#: ../src/fsckd/fsckd.c:186
+msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+msgstr ""
+
+#: ../src/fsckd/fsckd.c:227
+#, c-format
+msgid "Checking in progress on %d disk (%3.1f%% complete)"
+msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+msgstr[0] ""
+msgstr[1] ""
diff --git a/po/pt_BR.po b/po/pt_BR.po
index 5204047..072b8d3 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -419,3 +419,14 @@ msgstr "É necessária autenticação para recarregar o estado do sistema."
 
 #~ msgid "Privileged system and service manager access"
 #~ msgstr "Acesso privilegiado ao gerenciador de serviço e de sistema"
+
+#: ../src/fsckd/fsckd.c:186
+msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+msgstr ""
+
+#: ../src/fsckd/fsckd.c:227
+#, c-format
+msgid "Checking in progress on %d disk (%3.1f%% complete)"
+msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+msgstr[0] ""
+msgstr[1] ""
diff --git a/po/ru.po b/po/ru.po
index 4dda604..f07f333 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -325,3 +325,14 @@ msgstr "Перечитать конфигурацию systemd"
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
 msgid "Authentication is required to reload the systemd state."
 msgstr "Чтобы заставить systemd перечитать конфигурацию, необходимо пройти аутентификацию."
+
+#: ../src/fsckd/fsckd.c:186
+msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+msgstr ""
+
+#: ../src/fsckd/fsckd.c:227
+#, c-format
+msgid "Checking in progress on %d disk (%3.1f%% complete)"
+msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+msgstr[0] ""
+msgstr[1] ""
diff --git a/po/sv.po b/po/sv.po
index 25d4ae8..132b2ab 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -401,3 +401,14 @@ msgstr "Läs om tillståndet för systemd"
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
 msgid "Authentication is required to reload the systemd state."
 msgstr "Autentisering krävs för att läsa om tillståndet för systemd."
+
+#: ../src/fsckd/fsckd.c:186
+msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+msgstr ""
+
+#: ../src/fsckd/fsckd.c:227
+#, c-format
+msgid "Checking in progress on %d disk (%3.1f%% complete)"
+msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+msgstr[0] ""
+msgstr[1] ""
diff --git a/po/uk.po b/po/uk.po
index 6e32236..3603999 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -375,3 +375,15 @@ msgstr "Привілейований доступ до менеджера сис
 #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
 msgid "Authentication is required to access the system and service manager."
 msgstr "Засвідчення потрібно, щоб доступитись до менеджера системи і служб."
+
+#: ../src/fsckd/fsckd.c:186
+msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+msgstr ""
+
+#: ../src/fsckd/fsckd.c:227
+#, c-format
+msgid "Checking in progress on %d disk (%3.1f%% complete)"
+msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""

commit b0d924648600ac10101b22cdfc2b055d502fd899
Author: Didier Roche <didrocks at ubuntu.com>
Date:   Mon Jan 26 17:12:54 2015 +0100

    Translate fsckd messages for plymouth
    
    For plymouth themes not supporting i18n (like .script), send translated
    messages to display to user, which is equivalent to the sent machine
    readable data.

diff --git a/po/POTFILES.in b/po/POTFILES.in
index b4c1121..70e7594 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -5,3 +5,4 @@ src/locale/org.freedesktop.locale1.policy.in
 src/login/org.freedesktop.login1.policy.in
 src/machine/org.freedesktop.machine1.policy.in
 src/timedate/org.freedesktop.timedate1.policy.in
+src/fsckd/fsckd.c
diff --git a/src/fsckd/fsckd.c b/src/fsckd/fsckd.c
index dc00fc6..834476c 100644
--- a/src/fsckd/fsckd.c
+++ b/src/fsckd/fsckd.c
@@ -24,6 +24,7 @@
 
 #include <getopt.h>
 #include <errno.h>
+#include <libintl.h>
 #include <math.h>
 #include <stdbool.h>
 #include <stdlib.h>
@@ -182,7 +183,7 @@ static int send_message_plymouth(Manager *m, const char *message) {
                 if (r < 0)
                         return log_warning_errno(errno, "Can't send to plymouth cancel key: %m");
                 m->plymouth_cancel_sent = true;
-                plymouth_cancel_message = strjoina("fsckd-cancel-msg:", "Press Ctrl+C to cancel all filesystem checks in progress");
+                plymouth_cancel_message = strjoina("fsckd-cancel-msg:", _("Press Ctrl+C to cancel all filesystem checks in progress"));
                 r = send_message_plymouth_socket(m->plymouth_fd, plymouth_cancel_message, false);
                 if (r < 0)
                         log_warning_errno(r, "Can't send filesystem cancel message to plymouth: %m");
@@ -222,8 +223,10 @@ static int update_global_progress(Manager *m) {
                 m->numdevices = current_numdevices;
                 m->percent = current_percent;
 
-                if (asprintf(&console_message, "Checking in progress on %d disks (%3.1f%% complete)",
-                                                m->numdevices, m->percent) < 0)
+                if (asprintf(&console_message,
+                             ngettext("Checking in progress on %d disk (%3.1f%% complete)",
+                                      "Checking in progress on %d disks (%3.1f%% complete)", m->numdevices),
+                                      m->numdevices, m->percent) < 0)
                         return -ENOMEM;
                 if (asprintf(&fsck_message, "fsckd:%d:%3.1f:%s", m->numdevices, m->percent, console_message) < 0)
                         return -ENOMEM;
@@ -507,6 +510,7 @@ int main(int argc, char *argv[]) {
         log_set_target(LOG_TARGET_AUTO);
         log_parse_environment();
         log_open();
+        init_gettext();
 
         r = parse_argv(argc, argv);
         if (r <= 0)

commit 20f56fddcd58c84fa73597486e905c652667214f
Author: Didier Roche <didrocks at ubuntu.com>
Date:   Thu Jan 29 16:12:58 2015 +0100

    Add gettext support

diff --git a/configure.ac b/configure.ac
index 277addb..9a2235b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,6 +73,7 @@ AS_IF([test -z "$INTLTOOL_POLICY_RULE"], [
 
 GETTEXT_PACKAGE=systemd
 AC_SUBST(GETTEXT_PACKAGE)
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [systemd])
 
 AC_PROG_MKDIR_P
 AC_PROG_LN_S
diff --git a/src/shared/util.c b/src/shared/util.c
index ba035ca..deb9839 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -25,6 +25,8 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <libintl.h>
+#include <locale.h>
 #include <stdio.h>
 #include <syslog.h>
 #include <sched.h>
@@ -74,6 +76,7 @@
 #include <sys/auxv.h>
 #endif
 
+#include "config.h"
 #include "macro.h"
 #include "util.h"
 #include "ioprio.h"
@@ -5782,6 +5785,11 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
         return NULL;
 }
 
+void init_gettext(void) {
+        setlocale(LC_ALL, "");
+        textdomain(GETTEXT_PACKAGE);
+}
+
 bool is_locale_utf8(void) {
         const char *set;
         static int cached_answer = -1;
diff --git a/src/shared/util.h b/src/shared/util.h
index a83b588..45cb094 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -737,6 +737,8 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
                  int (*compar) (const void *, const void *, void *),
                  void *arg);
 
+#define _(String) gettext (String)
+void init_gettext(void);
 bool is_locale_utf8(void);
 
 typedef enum DrawSpecialChar {

commit 07f9a21b6d2a8a7cfd8928a329b1ce9c479e3972
Author: Didier Roche <didrocks at ubuntu.com>
Date:   Thu Feb 5 17:08:18 2015 +0100

    Connect to plymouth and support cancellation of in progress fsck
    
    Try to connect and send to plymouth (if running) some checked report progress,
    using direct plymouth protocole.
    
    Update message is the following:
    fsckd:<num_devices>:<progress>:<string>
    * num_devices corresponds to the current number of devices being checked (int)
    * progress corresponds to the current minimum percentage of all devices being
      checked (float, from 0 to 100)
    * string is a translated message ready to be displayed by the plymouth theme
      displaying the information above. It can be overriden by plymouth themes
      supporting i18n.
    
    Grab in fsckd plymouth watch key Control+C, and propagate this cancel request
    to systemd-fsck which will terminate fsck.
    
    Send a message to signal to user what key we are grabbing for fsck cancel.
    
    Message is: fsckd-cancel-msg:<string>
    Where string is a translated string ready to be displayed by the plymouth theme
    indicating that Control+C can be used to cancel current checks. It can be
    overriden (matching only fsckd-cancel-msg prefix) for themes supporting i18n.

diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 9ecba99..e718534 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -132,7 +132,7 @@ static void test_files(void) {
 
 }
 
-static int process_progress(int fd, dev_t device_num) {
+static int process_progress(int fd, pid_t fsck_pid, dev_t device_num) {
         _cleanup_fclose_ FILE *f = NULL;
         usec_t last = 0;
         _cleanup_close_ int fsckd_fd = -1;
@@ -153,11 +153,13 @@ static int process_progress(int fd, dev_t device_num) {
 
         while (!feof(f)) {
                 int pass;
+                size_t buflen;
                 size_t cur, max;
-                ssize_t n;
+                ssize_t r;
                 usec_t t;
                 _cleanup_free_ char *device = NULL;
                 FsckProgress progress;
+                FsckdMessage fsckd_message;
 
                 if (fscanf(f, "%i %lu %lu %ms", &pass, &cur, &max, &device) != 4)
                         break;
@@ -175,9 +177,19 @@ static int process_progress(int fd, dev_t device_num) {
                 progress.max = max;
                 progress.pass = pass;
 
-                n = send(fsckd_fd, &progress, sizeof(FsckProgress), 0);
-                if (n < 0 || (size_t) n < sizeof(FsckProgress))
+                r = send(fsckd_fd, &progress, sizeof(FsckProgress), 0);
+                if (r < 0 || (size_t) r < sizeof(FsckProgress))
                         log_warning_errno(errno, "Cannot communicate fsck progress to fsckd: %m");
+
+                /* get fsckd requests, only read when we have coherent size data */
+                r = ioctl(fsckd_fd, FIONREAD, &buflen);
+                if (r == 0 && (size_t) buflen >= sizeof(FsckdMessage)) {
+                        r = recv(fsckd_fd, &fsckd_message, sizeof(FsckdMessage), 0);
+                        if (r > 0 && fsckd_message.cancel == 1) {
+                                log_info("Request to cancel fsck from fsckd");
+                                kill(fsck_pid, SIGTERM);
+                        }
+                }
         }
 
         return 0;
@@ -187,6 +199,7 @@ int main(int argc, char *argv[]) {
         const char *cmdline[9];
         int i = 0, r = EXIT_FAILURE, q;
         pid_t pid;
+        int progress_rc;
         siginfo_t status;
         _cleanup_udev_unref_ struct udev *udev = NULL;
         _cleanup_udev_device_unref_ struct udev_device *udev_device = NULL;
@@ -328,7 +341,7 @@ int main(int argc, char *argv[]) {
         progress_pipe[1] = safe_close(progress_pipe[1]);
 
         if (progress_pipe[0] >= 0) {
-                process_progress(progress_pipe[0], st.st_rdev);
+                progress_rc = process_progress(progress_pipe[0], pid, st.st_rdev);
                 progress_pipe[0] = -1;
         }
 
@@ -338,13 +351,14 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        if (status.si_code != CLD_EXITED || (status.si_status & ~1)) {
+        if (status.si_code != CLD_EXITED || (status.si_status & ~1) || progress_rc != 0) {
 
-                if (status.si_code == CLD_KILLED || status.si_code == CLD_DUMPED)
+                /* cancel will kill fsck (but process_progress returns 0) */
+                if ((progress_rc != 0 && status.si_code == CLD_KILLED) || status.si_code == CLD_DUMPED)
                         log_error("fsck terminated by signal %s.", signal_to_string(status.si_status));
                 else if (status.si_code == CLD_EXITED)
                         log_error("fsck failed with error code %i.", status.si_status);
-                else
+                else if (progress_rc != 0)
                         log_error("fsck failed due to unknown reason.");
 
                 if (status.si_code == CLD_EXITED && (status.si_status & 2) && root_directory)
@@ -355,7 +369,8 @@ int main(int argc, char *argv[]) {
                         start_target(SPECIAL_EMERGENCY_TARGET);
                 else {
                         r = EXIT_SUCCESS;
-                        log_warning("Ignoring error.");
+                        if (progress_rc != 0)
+                                log_warning("Ignoring error.");
                 }
 
         } else
diff --git a/src/fsckd/fsckd.c b/src/fsckd/fsckd.c
index 6b2eeb0..dc00fc6 100644
--- a/src/fsckd/fsckd.c
+++ b/src/fsckd/fsckd.c
@@ -34,6 +34,7 @@
 #include <unistd.h>
 
 #include "build.h"
+#include "def.h"
 #include "event-util.h"
 #include "fsckd.h"
 #include "log.h"
@@ -44,6 +45,7 @@
 #include "util.h"
 
 #define IDLE_TIME_SECONDS 30
+#define PLYMOUTH_REQUEST_KEY "K\2\2\3"
 
 struct Manager;
 
@@ -56,6 +58,7 @@ typedef struct Client {
         int pass;
         double percent;
         size_t buflen;
+        bool cancelled;
 
         LIST_FIELDS(struct Client, clients);
 } Client;
@@ -68,8 +71,13 @@ typedef struct Manager {
         FILE *console;
         double percent;
         int numdevices;
+        int plymouth_fd;
+        bool plymouth_cancel_sent;
+        bool cancel_requested;
 } Manager;
 
+static int connect_plymouth(Manager *m);
+static int update_global_progress(Manager *m);
 static void manager_free(Manager *m);
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
 #define _cleanup_manager_free_ _cleanup_(manager_freep)
@@ -92,6 +100,19 @@ static double compute_percent(int pass, size_t cur, size_t max) {
                 (double) cur / max;
 }
 
+static int request_cancel_client(Client *current) {
+        FsckdMessage cancel_msg;
+        ssize_t n;
+        cancel_msg.cancel = 1;
+
+        n = send(current->fd, &cancel_msg, sizeof(FsckdMessage), 0);
+        if (n < 0 || (size_t) n < sizeof(FsckdMessage))
+                return log_warning_errno(n, "Cannot send cancel to fsck on (%u, %u): %m",
+                                         major(current->devnum), minor(current->devnum));
+        else
+                current->cancelled = true;
+        return 0;
+}
 
 static void remove_client(Client **first, Client *item) {
         LIST_REMOVE(clients, *first, item);
@@ -99,10 +120,91 @@ static void remove_client(Client **first, Client *item) {
         free(item);
 }
 
+static void on_plymouth_disconnect(Manager *m) {
+        safe_close(m->plymouth_fd);
+        m->plymouth_fd = -1;
+        m->plymouth_cancel_sent = false;
+}
+
+static int plymouth_feedback_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
+        Client *current;
+        char buffer[6];
+        int r;
+
+        assert(m);
+
+        r = read(m->plymouth_fd, buffer, sizeof(buffer));
+        if (r <= 0)
+                on_plymouth_disconnect(m);
+        else {
+               if (buffer[0] == '\15')
+                       log_error("Message update to plymouth wasn't delivered successfully");
+
+               /* the only answer support type we requested is a key interruption */
+               if (buffer[0] == '\2' && buffer[5] == '\3') {
+                       m->cancel_requested = true;
+                       /* cancel all connected clients */
+                       LIST_FOREACH(clients, current, m->clients)
+                               request_cancel_client(current);
+               }
+        }
+
+        return 0;
+}
+
+static int send_message_plymouth_socket(int plymouth_fd, const char *message, bool update) {
+        _cleanup_free_ char *packet = NULL;
+        int r, n;
+        char mode = 'M';
+
+        if (update)
+                mode = 'U';
+
+        if (asprintf(&packet, "%c\002%c%s%n", mode, (int) (strlen(message) + 1), message, &n) < 0)
+                return log_oom();
+        r = loop_write(plymouth_fd, packet, n + 1, true);
+        return r;
+}
+
+
+static int send_message_plymouth(Manager *m, const char *message) {
+        int r;
+        const char *plymouth_cancel_message = NULL;
+
+        r = connect_plymouth(m);
+        if (r < 0)
+                return r;
+
+        if (!m->plymouth_cancel_sent) {
+                /* indicate to plymouth that we listen to Ctrl+C */
+                r = loop_write(m->plymouth_fd, PLYMOUTH_REQUEST_KEY, sizeof(PLYMOUTH_REQUEST_KEY), true);
+                if (r < 0)
+                        return log_warning_errno(errno, "Can't send to plymouth cancel key: %m");
+                m->plymouth_cancel_sent = true;
+                plymouth_cancel_message = strjoina("fsckd-cancel-msg:", "Press Ctrl+C to cancel all filesystem checks in progress");
+                r = send_message_plymouth_socket(m->plymouth_fd, plymouth_cancel_message, false);
+                if (r < 0)
+                        log_warning_errno(r, "Can't send filesystem cancel message to plymouth: %m");
+        } else if (m->numdevices == 0) {
+                m->plymouth_cancel_sent = false;
+                r = send_message_plymouth_socket(m->plymouth_fd, "", false);
+                if (r < 0)
+                        log_warning_errno(r, "Can't clear plymouth filesystem cancel message: %m");
+        }
+
+        r = send_message_plymouth_socket(m->plymouth_fd,  message, true);
+        if (r < 0)
+                return log_warning_errno(errno, "Couldn't send \"%s\" to plymouth: %m", message);
+
+        return 0;
+}
+
 static int update_global_progress(Manager *m) {
         Client *current = NULL;
         _cleanup_free_ char *console_message = NULL;
-        int current_numdevices = 0, l = 0;
+        _cleanup_free_ char *fsck_message = NULL;
+        int current_numdevices = 0, l = 0, r;
         double current_percent = 100;
 
         /* get the overall percentage */
@@ -123,6 +225,8 @@ static int update_global_progress(Manager *m) {
                 if (asprintf(&console_message, "Checking in progress on %d disks (%3.1f%% complete)",
                                                 m->numdevices, m->percent) < 0)
                         return -ENOMEM;
+                if (asprintf(&fsck_message, "fsckd:%d:%3.1f:%s", m->numdevices, m->percent, console_message) < 0)
+                        return -ENOMEM;
 
                 /* write to console */
                 if (m->console) {
@@ -130,12 +234,41 @@ static int update_global_progress(Manager *m) {
                         fflush(m->console);
                 }
 
+                /* try to connect to plymouth and send message */
+                r = send_message_plymouth(m, fsck_message);
+                if (r < 0)
+                        log_debug("Couldn't send message to plymouth");
+
                 if (l > m->clear)
                         m->clear = l;
         }
         return 0;
 }
 
+static int connect_plymouth(Manager *m) {
+        union sockaddr_union sa = PLYMOUTH_SOCKET;
+        int r;
+
+        /* try to connect or reconnect if sending a message */
+        if (m->plymouth_fd <= 0) {
+                m->plymouth_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
+                if (m->plymouth_fd < 0) {
+                        return log_warning_errno(errno, "Connection to plymouth socket failed: %m");
+                }
+                if (connect(m->plymouth_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
+                        on_plymouth_disconnect(m);
+                        return log_warning_errno(errno, "Couldn't connect to plymouth: %m");
+                }
+                r = sd_event_add_io(m->event, NULL, m->plymouth_fd, EPOLLIN, plymouth_feedback_handler, m);
+                if (r < 0) {
+                        on_plymouth_disconnect(m);
+                        return log_warning_errno(r, "Can't listen to plymouth socket: %m");
+                }
+        }
+
+        return 0;
+}
+
 static int progress_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
         Client *client = userdata;
         Manager *m = NULL;
@@ -146,6 +279,12 @@ static int progress_handler(sd_event_source *s, int fd, uint32_t revents, void *
         assert(client);
         m = client->manager;
 
+        /* check first if we need to cancel this client */
+        if (m->cancel_requested) {
+                if (!client->cancelled)
+                        request_cancel_client(client);
+        }
+
         /* ensure we have enough data to read */
         r = ioctl(fd, FIONREAD, &buflen);
         if (r == 0 && buflen != 0 && (size_t) buflen < sizeof(FsckProgress)) {
@@ -210,6 +349,9 @@ static int new_connection_handler(sd_event_source *s, int fd, uint32_t revents,
                         remove_client(&(m->clients), client);
                         return r;
                 }
+                /* only request the client to cancel now in case the request is dropped by the client (chance to recancel) */
+                if (m->cancel_requested)
+                        request_cancel_client(client);
         } else
                 return log_error_errno(errno, "Couldn't accept a new connection: %m");
 
@@ -233,6 +375,7 @@ static void manager_free(Manager *m) {
         }
 
         safe_close(m->connection_fd);
+        safe_close(m->plymouth_fd);
         if (m->console)
                 fclose(m->console);
 
@@ -266,6 +409,7 @@ static int manager_new(Manager **ret, int fd) {
         }
         m->percent = 100;
 
+        m->plymouth_fd = -1;
         *ret = m;
         m = NULL;
 
diff --git a/src/fsckd/fsckd.h b/src/fsckd/fsckd.h
index 6fe37a7..8239273 100644
--- a/src/fsckd/fsckd.h
+++ b/src/fsckd/fsckd.h
@@ -32,3 +32,7 @@ typedef struct FsckProgress {
         size_t max;
         int pass;
 } FsckProgress;
+
+typedef struct FsckdMessage {
+        uint8_t cancel;
+} FsckdMessage;

commit 19e887e709c31ee4366ec44a770d3963cd48cb86
Author: Didier Roche <didrocks at ubuntu.com>
Date:   Mon Jan 26 16:01:11 2015 +0100

    systemd-fsck: always connect to systemd-fsckd
    
    Remove the plymouth running or show-status checks from systemd-fsck. Instead,
    always connect to systemd-fsckd socket, and let this one decide if we display
    progress or not.

diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 6ccb2e7..9ecba99 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -45,7 +45,6 @@
 
 static bool arg_skip = false;
 static bool arg_force = false;
-static bool arg_show_progress = false;
 static const char *arg_repair = "-a";
 
 static void start_target(const char *target) {
@@ -131,8 +130,6 @@ static void test_files(void) {
         }
 #endif
 
-        if (access("/run/systemd/show-status", F_OK) >= 0 || plymouth_running())
-                arg_show_progress = true;
 }
 
 static int process_progress(int fd, dev_t device_num) {
@@ -286,11 +283,10 @@ int main(int argc, char *argv[]) {
                         log_warning_errno(r, "fsck.%s cannot be used for %s: %m", type, device);
         }
 
-        if (arg_show_progress)
-                if (pipe(progress_pipe) < 0) {
-                        log_error_errno(errno, "pipe(): %m");
-                        return EXIT_FAILURE;
-                }
+        if (pipe(progress_pipe) < 0) {
+                log_error_errno(errno, "pipe(): %m");
+                return EXIT_FAILURE;
+        }
 
         cmdline[i++] = "/sbin/fsck";
         cmdline[i++] =  arg_repair;
diff --git a/src/fsckd/fsckd.c b/src/fsckd/fsckd.c
index 39fe899..6b2eeb0 100644
--- a/src/fsckd/fsckd.c
+++ b/src/fsckd/fsckd.c
@@ -259,9 +259,11 @@ static int manager_new(Manager **ret, int fd) {
                 return r;
 
         m->connection_fd = fd;
-        m->console = fopen("/dev/console", "we");
-        if (!m->console)
-                return log_warning_errno(errno, "Can't connect to /dev/console: %m");
+        if (access("/run/systemd/show-status", F_OK) >= 0) {
+                m->console = fopen("/dev/console", "we");
+                if (!m->console)
+                        return log_warning_errno(errno, "Can't connect to /dev/console: %m");
+        }
         m->percent = 100;
 
         *ret = m;

commit ac6e2f0dfc2e800f01c79ecea2b811914110a7b9
Author: Didier Roche <didrocks at ubuntu.com>
Date:   Wed Feb 4 16:42:47 2015 +0100

    fsckd daemon for inter-fsckd communication
    
    Add systemd-fsckd multiplexer which accepts multiple systemd-fsck
    instances to connect to it and sends progress report. systemd-fsckd then
    computes and writes to /dev/console the number of devices currently being
    checked and the minimum fsck progress. This will be used for interactive
    progress report and cancelling in plymouth.
    
    systemd-fsckd stops on idle when no systemd-fsck is connected.
    
    Make the necessary changes to systemd-fsck to connect to the systemd-fsckd
    socket.

diff --git a/.gitignore b/.gitignore
index 2afbed4..1308147 100644
--- a/.gitignore
+++ b/.gitignore
@@ -77,6 +77,7 @@
 /systemd-evcat
 /systemd-firstboot
 /systemd-fsck
+/systemd-fsckd
 /systemd-fstab-generator
 /systemd-getty-generator
 /systemd-gnome-ask-password-agent
diff --git a/Makefile.am b/Makefile.am
index 2a07321..a15b53b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -391,6 +391,7 @@ rootlibexec_PROGRAMS = \
 	systemd-remount-fs \
 	systemd-reply-password \
 	systemd-fsck \
+	systemd-fsckd \
 	systemd-machine-id-commit \
 	systemd-ac-power \
 	systemd-sysctl \
@@ -2357,6 +2358,18 @@ systemd_fsck_LDADD = \
 	libsystemd-shared.la
 
 # ------------------------------------------------------------------------------
+systemd_fsckd_SOURCES = \
+	src/fsckd/fsckd.c \
+	$(NULL)
+
+systemd_fsckd_LDADD = \
+	libsystemd-internal.la \
+	libsystemd-label.la \
+	libsystemd-shared.la \
+	libudev-internal.la \
+	$(NULL)
+
+# ------------------------------------------------------------------------------
 systemd_machine_id_commit_SOURCES = \
 	src/machine-id-commit/machine-id-commit.c \
 	src/core/machine-id-setup.c \
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 78ceeb6..6ccb2e7 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -27,6 +27,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/file.h>
+#include <sys/stat.h>
 
 #include "sd-bus.h"
 #include "libudev.h"
@@ -39,6 +40,8 @@
 #include "fileio.h"
 #include "udev-util.h"
 #include "path-util.h"
+#include "socket-util.h"
+#include "fsckd/fsckd.h"
 
 static bool arg_skip = false;
 static bool arg_force = false;
@@ -132,58 +135,36 @@ static void test_files(void) {
                 arg_show_progress = true;
 }
 
-static double percent(int pass, unsigned long cur, unsigned long max) {
-        /* Values stolen from e2fsck */
-
-        static const int pass_table[] = {
-                0, 70, 90, 92, 95, 100
+static int process_progress(int fd, dev_t device_num) {
+        _cleanup_fclose_ FILE *f = NULL;
+        usec_t last = 0;
+        _cleanup_close_ int fsckd_fd = -1;
+        static const union sockaddr_union sa = {
+                .un.sun_family = AF_UNIX,
+                .un.sun_path = FSCKD_SOCKET_PATH,
         };
 
-        if (pass <= 0)
-                return 0.0;
-
-        if ((unsigned) pass >= ELEMENTSOF(pass_table) || max == 0)
-                return 100.0;
-
-        return (double) pass_table[pass-1] +
-                ((double) pass_table[pass] - (double) pass_table[pass-1]) *
-                (double) cur / (double) max;
-}
-
-static int process_progress(int fd) {
-        _cleanup_fclose_ FILE *console = NULL, *f = NULL;
-        usec_t last = 0;
-        bool locked = false;
-        int clear = 0;
+        fsckd_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+        if (fsckd_fd < 0)
+                return log_warning_errno(errno, "Cannot open fsckd socket, we won't report fsck progress: %m");
+        if (connect(fsckd_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0)
+                return log_warning_errno(errno, "Cannot connect to fsckd socket, we won't report fsck progress: %m");
 
         f = fdopen(fd, "r");
-        if (!f) {
-                safe_close(fd);
-                return -errno;
-        }
-
-        console = fopen("/dev/console", "we");
-        if (!console)
-                return -ENOMEM;
+        if (!f)
+                return log_warning_errno(errno, "Cannot connect to fsck, we won't report fsck progress: %m");
 
         while (!feof(f)) {
-                int pass, m;
-                unsigned long cur, max;
-                _cleanup_free_ char *device = NULL;
-                double p;
+                int pass;
+                size_t cur, max;
+                ssize_t n;
                 usec_t t;
+                _cleanup_free_ char *device = NULL;
+                FsckProgress progress;
 
                 if (fscanf(f, "%i %lu %lu %ms", &pass, &cur, &max, &device) != 4)
                         break;
 
-                /* Only show one progress counter at max */
-                if (!locked) {
-                        if (flock(fileno(console), LOCK_EX|LOCK_NB) < 0)
-                                continue;
-
-                        locked = true;
-                }
-
                 /* Only update once every 50ms */
                 t = now(CLOCK_MONOTONIC);
                 if (last + 50 * USEC_PER_MSEC > t)
@@ -191,22 +172,15 @@ static int process_progress(int fd) {
 
                 last = t;
 
-                p = percent(pass, cur, max);
-                fprintf(console, "\r%s: fsck %3.1f%% complete...\r%n", device, p, &m);
-                fflush(console);
-
-                if (m > clear)
-                        clear = m;
-        }
-
-        if (clear > 0) {
-                unsigned j;
+                /* send progress to fsckd */
+                progress.devnum = device_num;
+                progress.cur = cur;
+                progress.max = max;
+                progress.pass = pass;
 
-                fputc('\r', console);
-                for (j = 0; j < (unsigned) clear; j++)
-                        fputc(' ', console);
-                fputc('\r', console);
-                fflush(console);
+                n = send(fsckd_fd, &progress, sizeof(FsckProgress), 0);
+                if (n < 0 || (size_t) n < sizeof(FsckProgress))
+                        log_warning_errno(errno, "Cannot communicate fsck progress to fsckd: %m");
         }
 
         return 0;
@@ -358,7 +332,7 @@ int main(int argc, char *argv[]) {
         progress_pipe[1] = safe_close(progress_pipe[1]);
 
         if (progress_pipe[0] >= 0) {
-                process_progress(progress_pipe[0]);
+                process_progress(progress_pipe[0], st.st_rdev);
                 progress_pipe[0] = -1;
         }
 
diff --git a/src/fsckd/Makefile b/src/fsckd/Makefile
new file mode 120000
index 0000000..d0b0e8e
--- /dev/null
+++ b/src/fsckd/Makefile
@@ -0,0 +1 @@
+../Makefile
\ No newline at end of file
diff --git a/src/fsckd/fsckd.c b/src/fsckd/fsckd.c
new file mode 100644
index 0000000..39fe899
--- /dev/null
+++ b/src/fsckd/fsckd.c
@@ -0,0 +1,404 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Canonical
+
+  Author:
+    Didier Roche <didrocks at ubuntu.com>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <getopt.h>
+#include <errno.h>
+#include <math.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "build.h"
+#include "event-util.h"
+#include "fsckd.h"
+#include "log.h"
+#include "list.h"
+#include "macro.h"
+#include "sd-daemon.h"
+#include "socket-util.h"
+#include "util.h"
+
+#define IDLE_TIME_SECONDS 30
+
+struct Manager;
+
+typedef struct Client {
+        struct Manager *manager;
+        int fd;
+        dev_t devnum;
+        size_t cur;
+        size_t max;
+        int pass;
+        double percent;
+        size_t buflen;
+
+        LIST_FIELDS(struct Client, clients);
+} Client;
+
+typedef struct Manager {
+        sd_event *event;
+        Client *clients;
+        int clear;
+        int connection_fd;
+        FILE *console;
+        double percent;
+        int numdevices;
+} Manager;
+
+static void manager_free(Manager *m);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
+#define _cleanup_manager_free_ _cleanup_(manager_freep)
+
+static double compute_percent(int pass, size_t cur, size_t max) {
+        /* Values stolen from e2fsck */
+
+        static const double pass_table[] = {
+                0, 70, 90, 92, 95, 100
+        };
+
+        if (pass <= 0)
+                return 0.0;
+
+        if ((unsigned) pass >= ELEMENTSOF(pass_table) || max == 0)
+                return 100.0;
+
+        return pass_table[pass-1] +
+                (pass_table[pass] - pass_table[pass-1]) *
+                (double) cur / max;
+}
+
+
+static void remove_client(Client **first, Client *item) {
+        LIST_REMOVE(clients, *first, item);
+        safe_close(item->fd);
+        free(item);
+}
+
+static int update_global_progress(Manager *m) {
+        Client *current = NULL;
+        _cleanup_free_ char *console_message = NULL;
+        int current_numdevices = 0, l = 0;
+        double current_percent = 100;
+
+        /* get the overall percentage */
+        LIST_FOREACH(clients, current, m->clients) {
+                current_numdevices++;
+
+                /* right now, we only keep the minimum % of all fsckd processes. We could in the future trying to be
+                   linear, but max changes and corresponds to the pass. We have all the informations into fsckd
+                   already if we can treat that in a smarter way. */
+                current_percent = MIN(current_percent, current->percent);
+        }
+
+        /* update if there is anything user-visible to update */
+        if (fabs(current_percent - m->percent) > 0.001 || current_numdevices != m->numdevices) {
+                m->numdevices = current_numdevices;
+                m->percent = current_percent;
+
+                if (asprintf(&console_message, "Checking in progress on %d disks (%3.1f%% complete)",
+                                                m->numdevices, m->percent) < 0)
+                        return -ENOMEM;
+
+                /* write to console */
+                if (m->console) {
+                        fprintf(m->console, "\r%s\r%n", console_message, &l);
+                        fflush(m->console);
+                }
+
+                if (l > m->clear)
+                        m->clear = l;
+        }
+        return 0;
+}
+
+static int progress_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        Client *client = userdata;
+        Manager *m = NULL;
+        FsckProgress fsck_data;
+        size_t buflen;
+        int r;
+
+        assert(client);
+        m = client->manager;
+
+        /* ensure we have enough data to read */
+        r = ioctl(fd, FIONREAD, &buflen);
+        if (r == 0 && buflen != 0 && (size_t) buflen < sizeof(FsckProgress)) {
+                if (client->buflen != buflen)
+                        client->buflen = buflen;
+                /* we got twice the same size from a bad behaving client, kick it off the list */
+                else {
+                        log_warning("Closing bad behaving fsck client connection at fd %d", client->fd);
+                        remove_client(&(m->clients), client);
+                        r = update_global_progress(m);
+                        if (r < 0)
+                                log_warning_errno(r, "Couldn't update global progress: %m");
+                }
+                return 0;
+        }
+
+        /* read actual data */
+        r = recv(fd, &fsck_data, sizeof(FsckProgress), 0);
+        if (r == 0) {
+                log_debug("Fsck client connected to fd %d disconnected", client->fd);
+                remove_client(&(m->clients), client);
+        } else if (r > 0 && r != sizeof(FsckProgress))
+                log_warning("Unexpected data structure sent to fsckd socket from fd: %d. Ignoring", client->fd);
+        else if (r > 0 && r == sizeof(FsckProgress)) {
+                client->devnum = fsck_data.devnum;
+                client->cur = fsck_data.cur;
+                client->max = fsck_data.max;
+                client->pass = fsck_data.pass;
+                client->percent = compute_percent(client->pass, client->cur, client->max);
+                log_debug("Getting progress for %u:%u (%lu, %lu, %d) : %3.1f%%",
+                          major(client->devnum), minor(client->devnum),
+                          client->cur, client->max, client->pass, client->percent);
+        } else
+                log_error_errno(r, "Unknown error while trying to read fsck data: %m");
+
+        r = update_global_progress(m);
+        if (r < 0)
+                log_warning_errno(r, "Couldn't update global progress: %m");
+
+        return 0;
+}
+
+static int new_connection_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
+        Client *client = NULL;
+        int new_client_fd, r;
+
+        assert(m);
+
+        /* Initialize and list new clients */
+        new_client_fd = accept4(m->connection_fd, NULL, NULL, SOCK_CLOEXEC);
+        if (new_client_fd > 0) {
+                log_debug("New fsck client connected to fd: %d", new_client_fd);
+                client = new0(Client, 1);
+                if (!client)
+                        return log_oom();
+                client->fd = new_client_fd;
+                client->manager = m;
+                LIST_PREPEND(clients, m->clients, client);
+                r = sd_event_add_io(m->event, NULL, client->fd, EPOLLIN, progress_handler, client);
+                if (r < 0) {
+                        remove_client(&(m->clients), client);
+                        return r;
+                }
+        } else
+                return log_error_errno(errno, "Couldn't accept a new connection: %m");
+
+        return 0;
+}
+
+static void manager_free(Manager *m) {
+        Client *current = NULL, *l = NULL;
+        if (!m)
+                return;
+
+        /* clear last line */
+        if (m->console && m->clear > 0) {
+                unsigned j;
+
+                fputc('\r', m->console);
+                for (j = 0; j < (unsigned) m->clear; j++)
+                        fputc(' ', m->console);
+                fputc('\r', m->console);
+                fflush(m->console);
+        }
+
+        safe_close(m->connection_fd);
+        if (m->console)
+                fclose(m->console);
+
+        LIST_FOREACH_SAFE(clients, current, l, m->clients)
+                remove_client(&(m->clients), current);
+
+        sd_event_unref(m->event);
+
+        free(m);
+}
+
+static int manager_new(Manager **ret, int fd) {
+        _cleanup_manager_free_ Manager *m = NULL;
+        int r;
+
+        assert(ret);
+
+        m = new0(Manager, 1);
+        if (!m)
+                return -ENOMEM;
+
+        r = sd_event_default(&m->event);
+        if (r < 0)
+                return r;
+
+        m->connection_fd = fd;
+        m->console = fopen("/dev/console", "we");
+        if (!m->console)
+                return log_warning_errno(errno, "Can't connect to /dev/console: %m");
+        m->percent = 100;
+
+        *ret = m;
+        m = NULL;
+
+        return 0;
+}
+
+static int run_event_loop_with_timeout(sd_event *e, usec_t timeout) {
+        int r, code;
+
+        assert(e);
+
+        for (;;) {
+                r = sd_event_get_state(e);
+                if (r < 0)
+                        return r;
+                if (r == SD_EVENT_FINISHED)
+                        break;
+
+                r = sd_event_run(e, timeout);
+                if (r < 0)
+                        return r;
+
+                /* timeout reached */
+                if (r == 0) {
+                        sd_event_exit(e, 0);
+                        break;
+                }
+        }
+
+        r = sd_event_get_exit_code(e, &code);
+        if (r < 0)
+                return r;
+
+        return code;
+}
+
+static void help(void) {
+        printf("%s [OPTIONS...]\n\n"
+               "Capture fsck progress and forward one stream to plymouth\n\n"
+               "  -h --help             Show this help\n"
+               "     --version          Show package version\n",
+               program_invocation_short_name);
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+        enum {
+                ARG_VERSION = 0x100,
+                ARG_ROOT,
+        };
+
+        static const struct option options[] = {
+                { "help",      no_argument,       NULL, 'h'           },
+                { "version",   no_argument,       NULL, ARG_VERSION   },
+                {}
+        };
+
+        int c;
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "hv", options, NULL)) >= 0)
+                switch (c) {
+
+                case 'h':
+                        help();
+                        return 0;
+
+                case ARG_VERSION:
+                        puts(PACKAGE_STRING);
+                        puts(SYSTEMD_FEATURES);
+                        return 0;
+
+                case '?':
+                        return -EINVAL;
+
+                default:
+                        assert_not_reached("Unhandled option");
+                }
+
+        if (optind < argc) {
+                log_error("Extraneous arguments");
+                return -EINVAL;
+        }
+
+        return 1;
+}
+
+int main(int argc, char *argv[]) {
+        _cleanup_manager_free_ Manager *m = NULL;
+        int fd = -1;
+        int r, n;
+
+        log_set_target(LOG_TARGET_AUTO);
+        log_parse_environment();
+        log_open();
+
+        r = parse_argv(argc, argv);
+        if (r <= 0)
+                return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+
+        n = sd_listen_fds(0);
+        if (n > 1) {
+                log_error("Too many file descriptors received.");
+                return EXIT_FAILURE;
+        } else if (n == 1) {
+                fd = SD_LISTEN_FDS_START + 0;
+        } else {
+                fd = make_socket_fd(LOG_DEBUG, FSCKD_SOCKET_PATH, SOCK_STREAM | SOCK_CLOEXEC);
+                if (fd < 0) {
+                        log_error_errno(r, "Couldn't create listening socket fd on %s: %m", FSCKD_SOCKET_PATH);
+                        return EXIT_FAILURE;
+                }
+        }
+
+        r = manager_new(&m, fd);
+        if (r < 0) {
+                log_error_errno(r, "Failed to allocate manager: %m");
+                return EXIT_FAILURE;
+        }
+
+        r = sd_event_add_io(m->event, NULL, fd, EPOLLIN, new_connection_handler, m);
+        if (r < 0) {
+                log_error_errno(r, "Can't listen to connection socket: %m");
+                return EXIT_FAILURE;
+        }
+
+        r = run_event_loop_with_timeout(m->event, IDLE_TIME_SECONDS * USEC_PER_SEC);
+        if (r < 0) {
+                log_error_errno(r, "Failed to run event loop: %m");
+                return EXIT_FAILURE;
+        }
+
+        sd_event_get_exit_code(m->event, &r);
+
+        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/src/fsckd/fsckd.h b/src/fsckd/fsckd.h
new file mode 100644
index 0000000..6fe37a7
--- /dev/null
+++ b/src/fsckd/fsckd.h
@@ -0,0 +1,34 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Canonical
+
+  Author:
+    Didier Roche <didrocks at ubuntu.com>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#define FSCKD_SOCKET_PATH "/run/systemd/fsckd"
+
+#include "libudev.h"
+
+typedef struct FsckProgress {
+        dev_t devnum;
+        size_t cur;
+        size_t max;
+        int pass;
+} FsckProgress;



More information about the systemd-commits mailing list