[systemd-commits] 7 commits - configure.ac .gitignore Makefile.am Makefile-man.am man/systemd-analyze.xml man/systemd-verify.xml shell-completion/bash shell-completion/zsh src/analyze src/shared src/sysusers src/update-done src/verify TODO

Zbigniew Jędrzejewski-Szmek zbyszek at kemper.freedesktop.org
Mon Jul 21 19:49:48 PDT 2014


 .gitignore                            |    1 
 Makefile-man.am                       |    2 
 Makefile.am                           |   31 +-
 TODO                                  |    3 
 configure.ac                          |    2 
 man/systemd-analyze.xml               |  122 ++++++++++-
 man/systemd-verify.xml                |  174 ----------------
 shell-completion/bash/systemctl.in    |    2 
 shell-completion/bash/systemd-analyze |    9 
 shell-completion/zsh/_sd_unit_files   |    9 
 shell-completion/zsh/_systemctl.in    |    6 
 shell-completion/zsh/_systemd-analyze |   12 +
 src/analyze/analyze-verify.c          |  280 ++++++++++++++++++++++++++
 src/analyze/analyze-verify.h          |   26 ++
 src/analyze/analyze.c                 |   94 +++++---
 src/shared/fileio-label.c             |    2 
 src/shared/missing.h                  |   12 +
 src/shared/path-lookup.c              |    2 
 src/sysusers/sysusers.c               |   45 ++--
 src/update-done/update-done.c         |   25 +-
 src/verify/Makefile                   |    1 
 src/verify/verify.c                   |  363 ----------------------------------
 22 files changed, 582 insertions(+), 641 deletions(-)

New commits:
commit 142c4ecaa9840714d49b40b1de407748b52f21d7
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Mon Jul 21 21:14:08 2014 -0400

    man: merge systemd-verify with systemd-analyze

diff --git a/Makefile-man.am b/Makefile-man.am
index 5cc3081..4339e50 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -92,7 +92,6 @@ MANPAGES += \
 	man/systemd-udevd.service.8 \
 	man/systemd-update-done.service.8 \
 	man/systemd-update-utmp.service.8 \
-	man/systemd-verify.1 \
 	man/systemd.1 \
 	man/systemd.automount.5 \
 	man/systemd.device.5 \
@@ -1659,7 +1658,6 @@ EXTRA_DIST += \
 	man/systemd-update-utmp.service.xml \
 	man/systemd-user-sessions.service.xml \
 	man/systemd-vconsole-setup.service.xml \
-	man/systemd-verify.xml \
 	man/systemd.automount.xml \
 	man/systemd.device.xml \
 	man/systemd.directives.xml \
diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml
index c7a2598..073e807 100644
--- a/man/systemd-analyze.xml
+++ b/man/systemd-analyze.xml
@@ -95,6 +95,12 @@
                         <arg choice="plain">set-log-level</arg>
                         <arg choice="opt"><replaceable>LEVEL</replaceable></arg>
                 </cmdsynopsis>
+                <cmdsynopsis>
+                        <command>systemd-analyze</command>
+                        <arg choice="opt" rep="repeat">OPTIONS</arg>
+                        <arg choice="plain">verify</arg>
+                        <arg choice="opt" rep="repeat"><replaceable>FILES</replaceable></arg>
+                </cmdsynopsis>
         </refsynopsisdiv>
 
         <refsect1>
@@ -103,7 +109,8 @@
                 <para><command>systemd-analyze</command> may be used
                 to determine system boot-up performance statistics and
                 retrieve other state and tracing information from the
-                system and service manager.</para>
+                system and service manager, and to verify the
+                correctness of unit files.</para>
 
                 <para><command>systemd-analyze time</command>
                 prints the time spent in the kernel before
@@ -171,6 +178,17 @@
                 described in
                 <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).</para>
 
+                <para><command>systemd-analyze verify</command> will
+                load unit files and print warnings if any errors are
+                detected. Files specified on the command line will be
+                loaded, but also any other units referenced by
+                them. This command works by prepending the directories
+                for all command line arguments at the beginning of the
+                unit load path, which means that all units files found
+                in those directories will be used in preference to the
+                unit files found in the standard locations, even if
+                not listed explicitly.</para>
+
                 <para>If no command is passed, <command>systemd-analyze
                 time</command> is implied.</para>
 
@@ -185,17 +203,16 @@
                         <varlistentry>
                                 <term><option>--user</option></term>
 
-                                <listitem><para>Shows performance data
-                                of user sessions instead of the system
-                                manager.</para></listitem>
+                                <listitem><para>Operates on the user
+                                systemd instance.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
                                 <term><option>--system</option></term>
 
-                                <listitem><para>Shows performance data
-                                of the system manager. This is the
-                                implied default.</para></listitem>
+                                <listitem><para>Operates on the system
+                                systemd instance. This is the implied
+                                default.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
@@ -257,6 +274,14 @@
                                 e.g. "50ms".</para></listitem>
                         </varlistentry>
 
+                        <varlistentry>
+                                <term><option>--no-man</option></term>
+
+                                <listitem><para>Do not invoke man to verify the existence
+                                of man pages listen in <varname>Documentation=</varname>.
+                                </para></listitem>
+                        </varlistentry>
+
                         <xi:include href="user-system-options.xml" xpointer="host" />
                         <xi:include href="user-system-options.xml" xpointer="machine" />
 
@@ -275,20 +300,87 @@
         </refsect1>
 
         <refsect1>
-                <title>Examples</title>
+                <title>Examples for <command>dot</command></title>
 
-                <para>This plots all dependencies of any unit whose
-                name starts with <literal>avahi-daemon.</literal>:</para>
+                <example>
+                        <title>Plots all dependencies of any unit whose
+                        name starts with <literal>avahi-daemon</literal></title>
 
-                <programlisting>$ systemd-analyze dot 'avahi-daemon.*' | dot -Tsvg > avahi.svg
-$ eog avahi.svg</programlisting>
+                        <programlisting>$ systemd-analyze dot 'avahi-daemon.*' | dot -Tsvg > avahi.svg
+                        $ eog avahi.svg</programlisting>
+                </example>
 
-                <para>This plots the dependencies between all known target units:</para>
+                <example>
+                        <title>Plots the dependencies between all known target units</title>
 
-                <programlisting>systemd-analyze dot --to-pattern='*.target' --from-pattern='*.target' | dot -Tsvg > targets.svg
+                        <programlisting>systemd-analyze dot --to-pattern='*.target' --from-pattern='*.target' | dot -Tsvg > targets.svg
 $ eog targets.svg</programlisting>
+                </example>
+        </refsect1>
 
-
+        <refsect1>
+                <title>Examples for <command>verify</command></title>
+
+                <para>The following errors are currently detected:</para>
+                <itemizedlist>
+                        <listitem><para>unknown sections and
+                        directives, </para></listitem>
+
+                        <listitem><para>missing dependencies which are
+                        required to start the given unit,
+                        </para></listitem>
+
+                        <listitem><para>man pages listed in
+                        <varname>Documentation=</varname> which are
+                        not found in the system,</para></listitem>
+
+                        <listitem><para>commands listed in
+                        <varname>ExecStart=</varname> and similar
+                        which are not found in the system or not
+                        executable.</para></listitem>
+                </itemizedlist>
+
+                <example>
+                        <title>Misspelt directives</title>
+
+                        <programlisting>$ cat ./user.slice
+[Unit]
+WhatIsThis=11
+Documentation=man:nosuchfile(1)
+Requires=different.service
+
+[Service]
+Desription=x
+
+$ systemd-verify ./user.slice
+[./user.slice:9] Unknown lvalue 'WhatIsThis' in section 'Unit'
+[./user.slice:13] Unknown section 'Service'. Ignoring.
+Error: org.freedesktop.systemd1.LoadFailed:
+         Unit different.service failed to load:
+         No such file or directory.
+Failed to create user.slice/start: Invalid argument
+user.slice: man nosuchfile(1) command failed with code 16
+                        </programlisting>
+                </example>
+
+                <example>
+                        <title>Missing service units</title>
+
+                        <programlisting>$ tail ./a.socket ./b.socket
+==> ./a.socket <==
+[Socket]
+ListenStream=100
+
+==> ./b.socket <==
+[Socket]
+ListenStream=100
+Accept=yes
+
+$ systemd-verify ./a.socket ./b.socket
+Service a.service not loaded, a.socket cannot be started.
+Service b at 0.service not loaded, b.socket cannot be started.
+                        </programlisting>
+                </example>
         </refsect1>
 
         <xi:include href="less-variables.xml" />
diff --git a/man/systemd-verify.xml b/man/systemd-verify.xml
deleted file mode 100644
index 128032e..0000000
--- a/man/systemd-verify.xml
+++ /dev/null
@@ -1,174 +0,0 @@
-<?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 2014 Zbigniew Jędrzejewski-Szmek
-
-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-verify"
-          xmlns:xi="http://www.w3.org/2001/XInclude">
-
-  <refentryinfo>
-    <title>systemd-verify</title>
-    <productname>systemd</productname>
-
-    <authorgroup>
-      <author>
-        <contrib>Developer</contrib>
-        <firstname>Zbigniew</firstname>
-        <surname>Jędrzejewski-Szmek</surname>
-        <email>zbyszek at in.waw.pl</email>
-      </author>
-    </authorgroup>
-  </refentryinfo>
-
-  <refmeta>
-    <refentrytitle>systemd-verify</refentrytitle>
-    <manvolnum>1</manvolnum>
-  </refmeta>
-
-  <refnamediv>
-    <refname>systemd-verify</refname>
-    <refpurpose>Check unit file validity</refpurpose>
-  </refnamediv>
-
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>systemd-verify</command>
-      <arg choice="opt" rep="repeat">OPTIONS</arg>
-      <arg choice="opt" rep="repeat">FILES</arg>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-
-  <refsect1>
-    <title>Description</title>
-
-    <para><filename>systemd-verify</filename> will load unit files and
-    potentially print warnings if any errors are detected. Files
-    specified on the command line will be loaded, but also any other
-    units referenced by them.</para>
-
-    <para>This command works by prepending the directories for all
-    command line arguments at the beginning of the unit load path.
-    This means that all units files found in those directories will
-    be used in preference to the unit files found in the standard
-    locations, even if not listed explicitly.</para>
-
-    <para>The following errors are currently detected:</para>
-    <itemizedlist>
-      <listitem><para>unknown sections and directives,
-      </para></listitem>
-
-      <listitem><para>missing dependencies which are required to start
-      the given unit,</para></listitem>
-
-      <listitem><para>man pages listed in
-      <varname>Documentation=</varname> which are not found in the
-      system,</para></listitem>
-
-      <listitem><para>commands listed in <varname>ExecStart=</varname>
-      and similar which are not found in the system or not executable.
-      </para></listitem>
-    </itemizedlist>
-  </refsect1>
-
-  <refsect1>
-    <title>Options</title>
-
-    <para>The following options are understood:</para>
-
-    <variablelist>
-      <varlistentry>
-        <term><option>--no-man</option></term>
-
-        <listitem><para>Do not invoke man to verify the existence
-        of man pages listen in <varname>Documentation=</varname>.
-        </para></listitem>
-      </varlistentry>
-
-      <xi:include href="user-system-options.xml" xpointer="user" />
-      <xi:include href="user-system-options.xml" xpointer="system" />
-
-      <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.</para>
-  </refsect1>
-
-  <refsect1>
-    <title>Examples</title>
-
-    <example>
-      <title>Misspelt directives</title>
-
-      <programlisting>$ cat ./user.slice
-[Unit]
-WhatIsThis=11
-Documentation=man:systemd.nosuchfile(7)
-Requires=different.service
-
-[Service]
-Desription=x
-
-$ systemd-verify ./user.slice
-[./user.slice:9] Unknown lvalue 'WhatIsThis' in section 'Unit'
-[./user.slice:13] Unknown section 'Service'. Ignoring.
-Error: org.freedesktop.systemd1.LoadFailed: Unit different.service failed to load: No such file or directory.
-Failed to create user.slice/start: Invalid argument
-user.slice: man systemd.nosuchfile(7) command failed with code 16
-</programlisting>
-    </example>
-
-    <example>
-      <title>Missing service units</title>
-
-      <programlisting>$ tail ./a.socket ./b.socket
-==> ./a.socket <==
-[Socket]
-ListenStream=100
-
-==> ./b.socket <==
-[Socket]
-ListenStream=100
-Accept=yes
-
-$ systemd-verify ./a.socket ./b.socket
-Service a.service not loaded, a.socket cannot be started.
-Service b at 0.service not loaded, b.socket cannot be started.
-</programlisting>
-    </example>
-
-  </refsect1>
-
-  <refsect1>
-    <title>See Also</title>
-    <para>
-      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
-    </para>
-  </refsect1>
-</refentry>

commit 2c12a402cb1e8277c271ced8dc9c06d20b8f6017
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Mon Jul 21 21:11:56 2014 -0400

    shell-completion: systemd-analyze verify, systemctl link
    
    Some zsh completion helpers were not installed, so completion
    was broken.
    
    Add systemd-analyze verify. Make systemctl link complete only
    unit names.

diff --git a/Makefile.am b/Makefile.am
index 1cb77b9..55ed54d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -407,6 +407,8 @@ dist_zshcompletion_DATA = \
 	shell-completion/zsh/_systemd-analyze \
 	shell-completion/zsh/_systemd-run \
 	shell-completion/zsh/_sd_hosts_or_user_at_host \
+	shell-completion/zsh/_sd_outputmodes \
+	shell-completion/zsh/_sd_unit_files \
 	shell-completion/zsh/_systemd-delta \
 	shell-completion/zsh/_systemd
 
diff --git a/TODO b/TODO
index 4a1313d..d964b52 100644
--- a/TODO
+++ b/TODO
@@ -704,6 +704,9 @@ External:
 
 * register catalog database signature as file magic
 
+* zsh shell completion: <command> <verb> -<TAB> should complete options, but currently
+  does not
+
 Regularly:
 
 * look for close() vs. close_nointr() vs. close_nointr_nofail()
diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in
index 4beec4e..c5950cc 100644
--- a/shell-completion/bash/systemctl.in
+++ b/shell-completion/bash/systemctl.in
@@ -89,7 +89,7 @@ _systemctl () {
                                 comps=$(compgen -A signal)
                         ;;
                         --type|-t)
-                                comps='automount device mount path service snapshot socket swap target timer'
+                                comps='automount busname device mount path service snapshot socket swap target timer'
                         ;;
                         --state)
                                 comps='loaded not-found stub
diff --git a/shell-completion/bash/systemd-analyze b/shell-completion/bash/systemd-analyze
index 5575beb..77d1b54 100644
--- a/shell-completion/bash/systemd-analyze
+++ b/shell-completion/bash/systemd-analyze
@@ -44,6 +44,7 @@ _systemd_analyze() {
                 [CRITICAL_CHAIN]='critical-chain'
                 [DOT]='dot'
                 [LOG_LEVEL]='set-log-level'
+                [VERIFY]='verify'
         )
 
         _init_completion || return
@@ -99,6 +100,14 @@ _systemd_analyze() {
                         comps='debug info notice warning err crit alert emerg'
                 fi
 
+        elif __contains_word "$verb" ${VERBS[VERIFY]}; then
+                if [[ $cur = -* ]]; then
+                        comps='--help --version --system --user --no-man'
+                else
+                        comps=$( compgen -A file -- "$cur" )
+                        compopt -o filenames
+                fi
+
         fi
 
         COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
diff --git a/shell-completion/zsh/_sd_unit_files b/shell-completion/zsh/_sd_unit_files
new file mode 100644
index 0000000..4778a04
--- /dev/null
+++ b/shell-completion/zsh/_sd_unit_files
@@ -0,0 +1,9 @@
+#autoload
+
+_sd_unit_files() {
+    local files expl
+    files=( '*:files:->files' )
+
+    _description files expl 'unit file'
+    _files "$expl[@]" -g '*.(automount|busname|device|mount|path|service|snapshot|socket|swap|target|timer)'
+}
diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in
index d9b8d1c..d364d17 100644
--- a/shell-completion/zsh/_systemctl.in
+++ b/shell-completion/zsh/_systemctl.in
@@ -261,7 +261,9 @@ for fun in set-environment unset-environment ; do
   }
 done
 
-(( $+functions[_systemctl_link] )) || _systemctl_link() { _files }
+(( $+functions[_systemctl_link] )) || _systemctl_link() {
+   _sd_unit_files
+}
 
 # no systemctl completion for:
 #    [STANDALONE]='daemon-reexec daemon-reload default
@@ -297,7 +299,7 @@ _unit_states() {
 
 _unit_types() {
     local -a _types
-    _types=(automount device mount path service snapshot socket swap target timer)
+    _types=(automount busname device mount path service snapshot socket swap target timer)
     _values -s , "${_types[@]}"
 }
 
diff --git a/shell-completion/zsh/_systemd-analyze b/shell-completion/zsh/_systemd-analyze
index 2eda5fe..c101ad0 100644
--- a/shell-completion/zsh/_systemd-analyze
+++ b/shell-completion/zsh/_systemd-analyze
@@ -6,6 +6,10 @@ _systemd_analyze_set-log-level() {
     _describe -t level 'logging level' _levels || compadd "$@"
 }
 
+_systemd_analyze_verify() {
+    _sd_unit_files
+}
+
 _systemd_analyze_command(){
     local -a _systemd_analyze_cmds
     # Descriptions taken from systemd-analyze --help.
@@ -17,6 +21,7 @@ _systemd_analyze_command(){
         'dot:Dump dependency graph (in dot(1) format)'
         'dump:Dump server status'
         'set-log-level:Set systemd log threshold'
+        'verify:Check unit files for correctness'
     )
 
     if (( CURRENT == 1 )); then
@@ -38,7 +43,12 @@ _systemd_analyze_command(){
 
 _arguments \
     {-h,--help}'[Show help text.]' \
-    '--user[Shows performance data of user sessions instead of the system manager.]' \
+    '--system[Operate on system systemd instance.]' \
+    '--user[Operate on user systemd instance.]' \
+    '--no-pager[Do not user pager.]' \
+    '--no-man[Do not check man pages.]' \
     '--order[When generating graph for dot, show only order]' \
     '--require[When generating graph for dot, show only requirement]' \
+    {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \
+    {-M+,--machine=}'[Operate on local container]:machine' \
     '*::systemd-analyze commands:_systemd_analyze_command'

commit 1d3bc0177a1952473bbe45b5bbb4e4e4f69a84f4
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Mon Jul 21 21:11:54 2014 -0400

    Merge systemd-verify with systemd-analyze

diff --git a/.gitignore b/.gitignore
index 81bcc16..41fff4f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -122,7 +122,6 @@
 /systemd-update-utmp
 /systemd-user-sessions
 /systemd-vconsole-setup
-/systemd-verify
 /tags
 /test-architecture
 /test-async
diff --git a/Makefile.am b/Makefile.am
index 1cb7712..1cb77b9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -350,8 +350,7 @@ bin_PROGRAMS = \
 	systemd-delta \
 	systemd-analyze \
 	systemd-run \
-	systemd-path \
-	systemd-verify
+	systemd-path
 
 dist_bin_SCRIPTS = \
 	src/kernel-install/kernel-install
@@ -1226,19 +1225,6 @@ CLEANFILES += \
 
 # ------------------------------------------------------------------------------
 
-systemd_verify_SOURCES = \
-	src/verify/verify.c
-
-systemd_verify_CFLAGS = \
-	$(AM_CFLAGS) \
-	$(SECCOMP_CFLAGS)
-
-systemd_verify_LDADD = \
-	libsystemd-core.la \
-	$(RT_LIBS)
-
-# ------------------------------------------------------------------------------
-
 manual_tests += \
 	test-ns \
 	test-loopback \
@@ -1738,11 +1724,19 @@ endif
 
 # ------------------------------------------------------------------------------
 systemd_analyze_SOURCES = \
-	src/analyze/analyze.c
+	src/analyze/analyze.c \
+	src/analyze/analyze-verify.c \
+	src/analyze/analyze-verify.h
+
+systemd_verify_CFLAGS = \
+	$(AM_CFLAGS) \
+	$(SECCOMP_CFLAGS)
 
 systemd_analyze_LDADD = \
+	libsystemd-core.la \
 	libsystemd-internal.la \
-	libsystemd-shared.la
+	libsystemd-shared.la \
+	$(RT_LIBS)
 
 # ------------------------------------------------------------------------------
 systemd_initctl_SOURCES = \
diff --git a/src/analyze/analyze-verify.c b/src/analyze/analyze-verify.c
new file mode 100644
index 0000000..5b16b6c
--- /dev/null
+++ b/src/analyze/analyze-verify.c
@@ -0,0 +1,280 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Zbigniew Jędrzejewski-Szmek
+
+  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 <stdlib.h>
+#include <getopt.h>
+
+#include "manager.h"
+#include "bus-util.h"
+#include "log.h"
+#include "strv.h"
+#include "build.h"
+#include "pager.h"
+#include "analyze-verify.h"
+
+static int generate_path(char **var, char **filenames) {
+        char **filename;
+
+        _cleanup_strv_free_ char **ans = NULL;
+        int r;
+
+        STRV_FOREACH(filename, filenames) {
+                char *t;
+
+                t = dirname_malloc(*filename);
+                if (!t)
+                        return -ENOMEM;
+
+                r = strv_consume(&ans, t);
+                if (r < 0)
+                        return r;
+        }
+
+        assert_se(strv_uniq(ans));
+
+        r = strv_extend(&ans, "");
+        if (r < 0)
+                return r;
+
+        *var = strv_join(ans, ":");
+        if (!*var)
+                return -ENOMEM;
+
+        return 0;
+}
+
+static int verify_socket(Unit *u) {
+        int r;
+
+        assert(u);
+
+        if (u->type != UNIT_SOCKET)
+                return 0;
+
+        /* Cannot run this without the service being around */
+
+        /* This makes sure instance is created if necessary. */
+        r = socket_instantiate_service(SOCKET(u));
+        if (r < 0) {
+                log_error_unit(u->id, "Socket %s cannot be started, failed to create instance.",
+                               u->id);
+                return r;
+        }
+
+        /* This checks both type of sockets */
+        if (UNIT_ISSET(SOCKET(u)->service)) {
+                Service *service;
+
+                service = SERVICE(UNIT_DEREF(SOCKET(u)->service));
+                log_debug_unit(u->id, "%s uses %s", u->id, UNIT(service)->id);
+
+                if (UNIT(service)->load_state != UNIT_LOADED) {
+                        log_error_unit(u->id, "Service %s not loaded, %s cannot be started.",
+                                       UNIT(service)->id, u->id);
+                        return -ENOENT;
+                }
+        }
+
+        return 0;
+}
+
+static int verify_executable(Unit *u, ExecCommand *exec) {
+        if (exec == NULL)
+                return 0;
+
+        if (access(exec->path, X_OK) < 0) {
+                log_error_unit(u->id, "%s: command %s is not executable: %m",
+                               u->id, exec->path);
+                return -errno;
+        }
+
+        return 0;
+}
+
+static int verify_executables(Unit *u) {
+        ExecCommand *exec;
+        int r = 0, k;
+        unsigned i;
+
+        assert(u);
+
+        exec =  u->type == UNIT_SOCKET ? SOCKET(u)->control_command :
+                u->type == UNIT_MOUNT ? MOUNT(u)->control_command :
+                u->type == UNIT_SWAP ? SWAP(u)->control_command : NULL;
+        k = verify_executable(u, exec);
+        if (k < 0 && r == 0)
+                r = k;
+
+        if (u->type == UNIT_SERVICE)
+                for (i = 0; i < ELEMENTSOF(SERVICE(u)->exec_command); i++) {
+                        k = verify_executable(u, SERVICE(u)->exec_command[i]);
+                        if (k < 0 && r == 0)
+                                r = k;
+                }
+
+        if (u->type == UNIT_SOCKET)
+                for (i = 0; i < ELEMENTSOF(SOCKET(u)->exec_command); i++) {
+                        k = verify_executable(u, SOCKET(u)->exec_command[i]);
+                        if (k < 0 && r == 0)
+                                r = k;
+                }
+
+        return r;
+}
+
+static int verify_documentation(Unit *u, bool check_man) {
+        char **p;
+        int r = 0, k;
+
+        STRV_FOREACH(p, u->documentation) {
+                log_debug_unit(u->id, "%s: found documentation item %s.", u->id, *p);
+                if (check_man && startswith(*p, "man:")) {
+                        k = show_man_page(*p + 4, true);
+                        if (k != 0) {
+                                if (k < 0)
+                                        log_error_unit(u->id, "%s: can't show %s: %s",
+                                                       u->id, *p, strerror(-r));
+                                else {
+                                        log_error_unit(u->id, "%s: man %s command failed with code %d",
+                                                       u->id, *p + 4, k);
+                                        k = -ENOEXEC;
+                                }
+                                if (r == 0)
+                                        r = k;
+                        }
+                }
+        }
+
+        /* Check remote URLs? */
+
+        return r;
+}
+
+static int verify_unit(Unit *u, bool check_man) {
+        _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
+        Job *j;
+        int r, k;
+
+        assert(u);
+
+        if (log_get_max_level() >= LOG_DEBUG)
+                unit_dump(u, stdout, "\t");
+
+        log_debug_unit(u->id, "Creating %s/start job", u->id);
+        r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, false, &err, &j);
+        if (sd_bus_error_is_set(&err))
+                log_error_unit(u->id, "Error: %s: %s",
+                               err.name, err.message);
+        if (r < 0)
+                log_error_unit(u->id, "Failed to create %s/start: %s",
+                               u->id, strerror(-r));
+
+        k = verify_socket(u);
+        if (k < 0 && r == 0)
+                r = k;
+
+        k = verify_executables(u);
+        if (k < 0 && r == 0)
+                r = k;
+
+        k = verify_documentation(u, check_man);
+        if (k < 0 && r == 0)
+                r = k;
+
+        return r;
+}
+
+int verify_units(char **filenames, SystemdRunningAs running_as, bool check_man) {
+        _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
+        Manager *m = NULL;
+        FILE *serial = NULL;
+        FDSet *fdset = NULL;
+
+        _cleanup_free_ char *var = NULL;
+
+        char **filename;
+        int r = 0, k;
+
+        Unit *units[strv_length(filenames)];
+        int i, count = 0;
+
+        if (strv_isempty(filenames))
+                return 0;
+
+        /* set the path */
+        r = generate_path(&var, filenames);
+        if (r < 0) {
+                log_error("Failed to generate unit load path: %s", strerror(-r));
+                return r;
+        }
+
+        assert_se(set_unit_path(var) >= 0);
+
+        r = manager_new(running_as, true, &m);
+        if (r < 0) {
+                log_error("Failed to initalize manager: %s", strerror(-r));
+                return r;
+        }
+
+        log_debug("Starting manager...");
+
+        r = manager_startup(m, serial, fdset);
+        if (r < 0) {
+                log_error("Failed to start manager: %s", strerror(-r));
+                goto finish;
+        }
+
+        manager_clear_jobs(m);
+
+        log_debug("Loading remaining units from the command line...");
+
+        STRV_FOREACH(filename, filenames) {
+                char fname[UNIT_NAME_MAX + 2 + 1] = "./";
+
+                log_debug("Handling %s...", *filename);
+
+                /* manager_load_unit does not like pure basenames, so prepend
+                 * the local directory, but only for valid names. manager_load_unit
+                 * will print the error for other ones. */
+                if (!strchr(*filename, '/') && strlen(*filename) <= UNIT_NAME_MAX) {
+                        strncat(fname + 2, *filename, UNIT_NAME_MAX);
+                        k = manager_load_unit(m, NULL, fname, &err, &units[count]);
+                } else
+                        k = manager_load_unit(m, NULL, *filename, &err, &units[count]);
+                if (k < 0) {
+                        log_error("Failed to load %s: %s", *filename, strerror(-k));
+                        if (r == 0)
+                                r = k;
+                } else
+                        count ++;
+        }
+
+        for (i = 0; i < count; i++) {
+                k = verify_unit(units[i], check_man);
+                if (k < 0 && r == 0)
+                        r = k;
+        }
+
+finish:
+        manager_free(m);
+
+        return r;
+}
diff --git a/src/analyze/analyze-verify.h b/src/analyze/analyze-verify.h
new file mode 100644
index 0000000..5c86d98
--- /dev/null
+++ b/src/analyze/analyze-verify.h
@@ -0,0 +1,26 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Zbigniew Jędrzejewski-Szmek
+
+  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 <stdbool.h>
+
+#include "path-lookup.h"
+
+int verify_units(char **filenames, SystemdRunningAs running_as, bool check_man);
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 0a4190c..66e2aab 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -41,6 +41,7 @@
 #include "special.h"
 #include "hashmap.h"
 #include "pager.h"
+#include "analyze-verify.h"
 
 #define SCALE_X (0.1 / 1000.0)   /* pixels per us */
 #define SCALE_Y (20.0)
@@ -74,6 +75,7 @@ static bool arg_no_pager = false;
 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
 static char *arg_host = NULL;
 static bool arg_user = false;
+static bool arg_man = true;
 
 struct boot_times {
         usec_t firmware_time;
@@ -1178,17 +1180,17 @@ static int set_log_level(sd_bus *bus, char **args) {
         return 0;
 }
 
-static int help(void) {
+static void help(void) {
 
         pager_open_if_enabled();
 
         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
-               "Process systemd profiling information.\n\n"
+               "Profile systemd, show unit dependencies, check unit files.\n\n"
                "  -h --help               Show this help\n"
                "     --version            Show package version\n"
                "     --no-pager           Do not pipe output into a pager\n"
-               "     --system             Connect to system manager\n"
-               "     --user               Connect to user manager\n"
+               "     --system             Operate on system systemd instance\n"
+               "     --user               Operate on user systemd instance\n"
                "  -H --host=[USER@]HOST   Operate on remote host\n"
                "  -M --machine=CONTAINER  Operate on local container\n"
                "     --order              When generating a dependency graph, show only order\n"
@@ -1200,6 +1202,7 @@ static int help(void) {
                "                          services, which finished TIMESPAN earlier, than the\n"
                "                          latest in the branch. The unit of TIMESPAN is seconds\n"
                "                          unless specified with a different unit, i.e. 50ms\n\n"
+               "     --no-man             Do not check for existence of man pages\n"
                "Commands:\n"
                "  time                    Print time spent in the kernel before reaching userspace\n"
                "  blame                   Print list of running units ordered by time to init\n"
@@ -1207,14 +1210,13 @@ static int help(void) {
                "  plot                    Output SVG graphic showing service initialization\n"
                "  dot                     Output dependency graph in dot(1) format\n"
                "  set-log-level LEVEL     Set logging threshold for systemd\n"
-               "  dump                    Output state serialization of service manager\n",
-               program_invocation_short_name);
+               "  dump                    Output state serialization of service manager\n"
+               "  verify                  Check unit files for correctness\n"
+               , program_invocation_short_name);
 
         /* When updating this list, including descriptions, apply
-         * changes to shell-completion/bash/systemd and
-         * shell-completion/systemd-zsh-completion.zsh too. */
-
-        return 0;
+         * changes to shell-completion/bash/systemd-analyze and
+         * shell-completion/zsh/_systemd-analyze too. */
 }
 
 static int parse_argv(int argc, char *argv[]) {
@@ -1227,7 +1229,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_DOT_FROM_PATTERN,
                 ARG_DOT_TO_PATTERN,
                 ARG_FUZZ,
-                ARG_NO_PAGER
+                ARG_NO_PAGER,
+                ARG_NO_MAN,
         };
 
         static const struct option options[] = {
@@ -1251,12 +1254,15 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
+        opterr = 0;
+
         while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0) {
 
                 switch (c) {
 
                 case 'h':
-                        return help();
+                        help();
+                        return 0;
 
                 case ARG_VERSION:
                         puts(PACKAGE_STRING);
@@ -1311,19 +1317,27 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_host = optarg;
                         break;
 
+                case ARG_NO_MAN:
+                        arg_man = false;
+                        break;
+
                 case '?':
+                        log_error("Unknown option %s.", argv[optind-1]);
+                        return -EINVAL;
+
+                case ':':
+                        log_error("Missing argument to %s.", argv[optind-1]);
                         return -EINVAL;
 
                 default:
-                        assert_not_reached("Unhandled option");
+                        assert_not_reached("Unhandled option code.");
                 }
         }
 
-        return 1;
+        return 1; /* work to do */
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_bus_unref_ sd_bus *bus = NULL;
         int r;
 
         setlocale(LC_ALL, "");
@@ -1335,28 +1349,36 @@ int main(int argc, char *argv[]) {
         if (r <= 0)
                 goto finish;
 
-        r = bus_open_transport_systemd(arg_transport, arg_host, arg_user, &bus);
-        if (r < 0) {
-                log_error("Failed to create bus connection: %s", strerror(-r));
-                goto finish;
-        }
+        if (streq(argv[optind], "verify"))
+                r = verify_units(argv+optind+1,
+                                 arg_user ? SYSTEMD_USER : SYSTEMD_SYSTEM,
+                                 arg_man);
+        else {
+                _cleanup_bus_unref_ sd_bus *bus = NULL;
+
+                r = bus_open_transport_systemd(arg_transport, arg_host, arg_user, &bus);
+                if (r < 0) {
+                        log_error("Failed to create bus connection: %s", strerror(-r));
+                        goto finish;
+                }
 
-        if (!argv[optind] || streq(argv[optind], "time"))
-                r = analyze_time(bus);
-        else if (streq(argv[optind], "blame"))
-                r = analyze_blame(bus);
-        else if (streq(argv[optind], "critical-chain"))
-                r = analyze_critical_chain(bus, argv+optind+1);
-        else if (streq(argv[optind], "plot"))
-                r = analyze_plot(bus);
-        else if (streq(argv[optind], "dot"))
-                r = dot(bus, argv+optind+1);
-        else if (streq(argv[optind], "dump"))
-                r = dump(bus, argv+optind+1);
-        else if (streq(argv[optind], "set-log-level"))
-                r = set_log_level(bus, argv+optind+1);
-        else
-                log_error("Unknown operation '%s'.", argv[optind]);
+                if (!argv[optind] || streq(argv[optind], "time"))
+                        r = analyze_time(bus);
+                else if (streq(argv[optind], "blame"))
+                        r = analyze_blame(bus);
+                else if (streq(argv[optind], "critical-chain"))
+                        r = analyze_critical_chain(bus, argv+optind+1);
+                else if (streq(argv[optind], "plot"))
+                        r = analyze_plot(bus);
+                else if (streq(argv[optind], "dot"))
+                        r = dot(bus, argv+optind+1);
+                else if (streq(argv[optind], "dump"))
+                        r = dump(bus, argv+optind+1);
+                else if (streq(argv[optind], "set-log-level"))
+                        r = set_log_level(bus, argv+optind+1);
+                else
+                        log_error("Unknown operation '%s'.", argv[optind]);
+        }
 
 finish:
         pager_close();
diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c
index 7a715b7..40fb0b8 100644
--- a/src/shared/path-lookup.c
+++ b/src/shared/path-lookup.c
@@ -212,7 +212,7 @@ int lookup_paths_init(
         if (!p->unit_path || append) {
                 /* Let's figure something out. */
 
-                char **unit_path;
+                _cleanup_strv_free_ char **unit_path;
                 int r;
 
                 /* For the user units we include share/ in the search
diff --git a/src/verify/Makefile b/src/verify/Makefile
deleted file mode 120000
index 94aaae2..0000000
--- a/src/verify/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../../Makefile
\ No newline at end of file
diff --git a/src/verify/verify.c b/src/verify/verify.c
deleted file mode 100644
index c1a3da8..0000000
--- a/src/verify/verify.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
-  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 <stdlib.h>
-#include <getopt.h>
-
-#include "manager.h"
-#include "bus-util.h"
-#include "log.h"
-#include "strv.h"
-#include "build.h"
-#include "pager.h"
-
-SystemdRunningAs arg_running_as = SYSTEMD_SYSTEM;
-bool arg_no_man = false;
-
-static int generate_path(char **var, char **filenames) {
-        char **filename;
-
-        _cleanup_strv_free_ char **ans = NULL;
-        int r;
-
-        STRV_FOREACH(filename, filenames) {
-                char *t;
-
-                t = dirname_malloc(*filename);
-                if (!t)
-                        return -ENOMEM;
-
-                r = strv_consume(&ans, t);
-                if (r < 0)
-                        return r;
-        }
-
-        assert_se(strv_uniq(ans));
-
-        r = strv_extend(&ans, "");
-        if (r < 0)
-                return r;
-
-        *var = strv_join(ans, ":");
-        if (!*var)
-                return -ENOMEM;
-
-        return 0;
-}
-
-static int verify_socket(Unit *u) {
-        int r;
-
-        assert(u);
-
-        if (u->type != UNIT_SOCKET)
-                return 0;
-
-        /* Cannot run this without the service being around */
-
-        /* This makes sure instance is created if necessary. */
-        r = socket_instantiate_service(SOCKET(u));
-        if (r < 0) {
-                log_error_unit(u->id, "Socket %s cannot be started, failed to create instance.",
-                               u->id);
-                return r;
-        }
-
-        /* This checks both type of sockets */
-        if (UNIT_ISSET(SOCKET(u)->service)) {
-                Service *service;
-
-                service = SERVICE(UNIT_DEREF(SOCKET(u)->service));
-                log_debug_unit(u->id, "%s uses %s", u->id, UNIT(service)->id);
-
-                if (UNIT(service)->load_state != UNIT_LOADED) {
-                        log_error_unit(u->id, "Service %s not loaded, %s cannot be started.",
-                                       UNIT(service)->id, u->id);
-                        return -ENOENT;
-                }
-        }
-
-        return 0;
-}
-
-static int verify_executable(Unit *u, ExecCommand *exec) {
-        if (exec == NULL)
-                return 0;
-
-        if (access(exec->path, X_OK) < 0) {
-                log_error_unit(u->id, "%s: command %s is not executable: %m",
-                               u->id, exec->path);
-                return -errno;
-        }
-
-        return 0;
-}
-
-static int verify_executables(Unit *u) {
-        ExecCommand *exec;
-        int r = 0, k;
-        unsigned i;
-
-        assert(u);
-
-        exec =  u->type == UNIT_SOCKET ? SOCKET(u)->control_command :
-                u->type == UNIT_MOUNT ? MOUNT(u)->control_command :
-                u->type == UNIT_SWAP ? SWAP(u)->control_command : NULL;
-        k = verify_executable(u, exec);
-        if (k < 0 && r == 0)
-                r = k;
-
-        if (u->type == UNIT_SERVICE)
-                for (i = 0; i < ELEMENTSOF(SERVICE(u)->exec_command); i++) {
-                        k = verify_executable(u, SERVICE(u)->exec_command[i]);
-                        if (k < 0 && r == 0)
-                                r = k;
-                }
-
-        if (u->type == UNIT_SOCKET)
-                for (i = 0; i < ELEMENTSOF(SOCKET(u)->exec_command); i++) {
-                        k = verify_executable(u, SOCKET(u)->exec_command[i]);
-                        if (k < 0 && r == 0)
-                                r = k;
-                }
-
-        return r;
-}
-
-static int verify_documentation(Unit *u) {
-        char **p;
-        int r = 0, k;
-
-        if (arg_no_man)
-                return 0;
-
-        STRV_FOREACH(p, u->documentation) {
-                log_debug_unit(u->id, "%s: found documentation item %s.", u->id, *p);
-                if (startswith(*p, "man:")) {
-                        k = show_man_page(*p + 4, true);
-                        if (k != 0) {
-                                if (k < 0)
-                                        log_error_unit(u->id, "%s: can't show %s: %s",
-                                                       u->id, *p, strerror(-r));
-                                else {
-                                        log_error_unit(u->id, "%s: man %s command failed with code %d",
-                                                       u->id, *p + 4, k);
-                                        k = -ENOEXEC;
-                                }
-                                if (r == 0)
-                                        r = k;
-                        }
-                }
-        }
-
-        /* Check remote URLs? */
-
-        return r;
-}
-
-static int test_unit(Unit *u) {
-        _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
-        Job *j;
-        int r, k;
-
-        assert(u);
-
-        if (log_get_max_level() >= LOG_DEBUG)
-                unit_dump(u, stdout, "\t");
-
-        log_debug_unit(u->id, "Creating %s/start job", u->id);
-        r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, false, &err, &j);
-        if (sd_bus_error_is_set(&err))
-                log_error_unit(u->id, "Error: %s: %s",
-                               err.name, err.message);
-        if (r < 0)
-                log_error_unit(u->id, "Failed to create %s/start: %s",
-                               u->id, strerror(-r));
-
-        k = verify_socket(u);
-        if (k < 0 && r == 0)
-                r = k;
-
-        k = verify_executables(u);
-        if (k < 0 && r == 0)
-                r = k;
-
-        k = verify_documentation(u);
-        if (k < 0 && r == 0)
-                r = k;
-
-        return r;
-}
-
-static int test_units(char **filenames) {
-        _cleanup_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
-        Manager *m = NULL;
-        FILE *serial = NULL;
-        FDSet *fdset = NULL;
-
-        _cleanup_free_ char *var;
-
-        char **filename;
-        int r = 0, k;
-
-        Unit *units[strv_length(filenames)];
-        int i, count = 0;
-
-        /* set the path */
-        r = generate_path(&var, filenames);
-        if (r < 0) {
-                log_error("Failed to generate unit load path: %s", strerror(-r));
-                return r;
-        }
-
-        assert_se(set_unit_path(var) >= 0);
-
-        r = manager_new(arg_running_as, true, &m);
-        if (r < 0) {
-                log_error("Failed to initalize manager: %s", strerror(-r));
-                return r;
-        }
-
-        log_debug("Starting manager...");
-
-        r = manager_startup(m, serial, fdset);
-        if (r < 0) {
-                log_error("Failed to start manager: %s", strerror(-r));
-                goto finish;
-        }
-
-        manager_clear_jobs(m);
-
-        log_debug("Loading remaining units from the command line...");
-
-        STRV_FOREACH(filename, filenames) {
-                log_debug("Handling %s...", *filename);
-
-                k = manager_load_unit(m, NULL, *filename, &err, &units[count]);
-                if (k < 0) {
-                        log_error("Failed to load %s: %s", *filename, strerror(-r));
-                        if (r == 0)
-                                r = k;
-                }
-
-                count ++;
-        }
-
-        for (i = 0; i < count; i++) {
-                k = test_unit(units[i]);
-                if (k < 0 && r == 0)
-                        r = k;
-        }
-
-finish:
-        manager_free(m);
-
-        return r;
-}
-
-static void help(void) {
-        printf("%s [OPTIONS...] {COMMAND} ...\n\n"
-               "Check if unit files can be correctly loaded.\n\n"
-               "  -h --help           Show this help\n"
-               "     --version        Show package version\n"
-               "     --system         Test system units\n"
-               "     --user           Test user units\n"
-               "     --no-man         Do not check for existence of man pages\n"
-               , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-        enum {
-                ARG_VERSION = 0x100,
-                ARG_USER,
-                ARG_SYSTEM,
-                ARG_NO_MAN,
-        };
-
-        static const struct option options[] = {
-                { "help",                no_argument,       NULL, 'h'                     },
-                { "version",             no_argument,       NULL, ARG_VERSION             },
-                { "user",                no_argument,       NULL, ARG_USER                },
-                { "system",              no_argument,       NULL, ARG_SYSTEM              },
-                {}
-        };
-
-        int c;
-
-        assert(argc >= 1);
-        assert(argv);
-
-        opterr = 0;
-
-        while ((c = getopt_long(argc, argv, ":h", options, NULL)) >= 0)
-                switch (c) {
-
-                case 'h':
-                        help();
-                        return 0;
-
-                case ARG_VERSION:
-                        puts(PACKAGE_STRING);
-                        puts(SYSTEMD_FEATURES);
-                        return 0;
-
-                case ARG_USER:
-                        arg_running_as = SYSTEMD_USER;
-                        break;
-
-                case ARG_SYSTEM:
-                        arg_running_as = SYSTEMD_SYSTEM;
-                        break;
-
-                case ARG_NO_MAN:
-                        arg_no_man = true;
-                        break;
-
-                case '?':
-                        log_error("Unknown option %s.", argv[optind-1]);
-                        return -EINVAL;
-
-                case ':':
-                        log_error("Missing argument to %s.", argv[optind-1]);
-                        return -EINVAL;
-
-                default:
-                        assert_not_reached("Unhandled option code.");
-                }
-
-        return 1; /* work to do */
-}
-
-int main(int argc, char *argv[]) {
-        int r;
-
-        log_parse_environment();
-        log_open();
-
-        r = parse_argv(argc, argv);
-        if (r <= 0)
-                goto finish;
-
-        r = test_units(argv + optind);
-
-finish:
-        return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-}

commit 1a40a3393e904fe4683f6d2b2450cfbd94a34000
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Mon Jul 21 21:07:19 2014 -0400

    configure: add -Wno-typedef-redefinition
    
    Message-ID: <CAJ+BJsz9Qy-JU25dUuGT2n0LMNzcOpoJNGNtbf_boSuT_6hONw at mail.gmail.com>

diff --git a/configure.ac b/configure.ac
index 8cbf764..43b6eef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -183,6 +183,7 @@ CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
         -Wno-unused-parameter \
         -Wno-missing-field-initializers \
         -Wno-unused-result \
+        -Wno-typedef-redefinition \
         -Werror=overflow \
         -Wdate-time \
         -Wnested-externs \

commit 6589d0dba2b1ccf2406db527c2c1b51c7143e117
Author: Jean-André Santoni <jean.andre.santoni at gmail.com>
Date:   Mon Jul 21 21:04:44 2014 -0400

    Add IFLA_VTI defines to missing.h

diff --git a/configure.ac b/configure.ac
index 6f888a2..8cbf764 100644
--- a/configure.ac
+++ b/configure.ac
@@ -311,6 +311,7 @@ AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at, setns, LO_FLAGS_PARTSCAN]
 ]])
 
 AC_CHECK_DECLS([IFLA_MACVLAN_FLAGS,
+                IFLA_VTI_REMOTE,
                 IFLA_PHYS_PORT_ID,
                 IFLA_BOND_AD_INFO,
                 IFLA_VLAN_PROTOCOL,
diff --git a/src/shared/missing.h b/src/shared/missing.h
index 818d704..2985285 100644
--- a/src/shared/missing.h
+++ b/src/shared/missing.h
@@ -380,6 +380,18 @@ static inline int setns(int fd, int nstype) {
 #define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1)
 #endif
 
+#if !HAVE_DECL_IFLA_VTI_REMOTE
+#define IFLA_VTI_UNSPEC 0
+#define IFLA_VTI_LINK 1
+#define IFLA_VTI_IKEY 2
+#define IFLA_VTI_OKEY 3
+#define IFLA_VTI_LOCAL 4
+#define IFLA_VTI_REMOTE 5
+#define __IFLA_VTI_MAX 6
+
+#define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1)
+#endif
+
 #if !HAVE_DECL_IFLA_PHYS_PORT_ID
 #undef IFLA_PROMISCUITY
 #define IFLA_PROMISCUITY 30

commit 7dbb1d08f66cd44b1296be3ee8e3629b989e19a8
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Mon Jul 21 20:56:29 2014 -0400

    update-done: set proper selinux context for .updated
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1121806

diff --git a/Makefile.am b/Makefile.am
index 1e4cfb3..1cb7712 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1771,6 +1771,7 @@ systemd_update_done_SOURCES = \
 
 systemd_update_done_LDADD = \
 	libsystemd-internal.la \
+	libsystemd-label.la \
 	libsystemd-shared.la
 
 # ------------------------------------------------------------------------------
diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c
index 10ba85c..b199a68 100644
--- a/src/update-done/update-done.c
+++ b/src/update-done/update-done.c
@@ -20,6 +20,7 @@
 ***/
 
 #include "util.h"
+#include "label.h"
 
 static int apply_timestamp(const char *path, struct timespec *ts) {
         struct timespec twice[2];
@@ -51,10 +52,20 @@ static int apply_timestamp(const char *path, struct timespec *ts) {
 
         } else if (errno == ENOENT) {
                 _cleanup_close_ int fd = -1;
+                int r;
 
                 /* The timestamp file doesn't exist yet? Then let's create it. */
 
+                r = label_context_set(path, S_IFREG);
+                if (r < 0) {
+                        log_error("Failed to set SELinux context for %s: %s",
+                                  path, strerror(-r));
+                        return r;
+                }
+
                 fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644);
+                label_context_clear();
+
                 if (fd < 0) {
 
                         if (errno == EROFS) {
@@ -83,7 +94,7 @@ static int apply_timestamp(const char *path, struct timespec *ts) {
 
 int main(int argc, char *argv[]) {
         struct stat st;
-        int r, q;
+        int r, q = 0;
 
         log_set_target(LOG_TARGET_AUTO);
         log_parse_environment();
@@ -94,11 +105,15 @@ int main(int argc, char *argv[]) {
                 return EXIT_FAILURE;
         }
 
-        r = apply_timestamp("/etc/.updated", &st.st_mtim);
+        r = label_init(NULL);
+        if (r < 0) {
+                log_error("SELinux setup failed: %s", strerror(-r));
+                goto finish;
+        }
 
+        r = apply_timestamp("/etc/.updated", &st.st_mtim);
         q = apply_timestamp("/var/.updated", &st.st_mtim);
-        if (q < 0 && r == 0)
-                r = q;
 
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+finish:
+        return r < 0 || q < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }

commit 9f1c19405a1ccaf59dcc8c32c13a1619541189ad
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Mon Jul 21 20:41:19 2014 -0400

    sysusers: fix selinux context of backup files
    
    Also, fix fopen_temporary_label to set proper context. By chance,
    all users so far used the same context, so the error didn't matter.
    
    Also, check return value from label_init().
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1121806

diff --git a/src/shared/fileio-label.c b/src/shared/fileio-label.c
index 417ca56..c3def3c 100644
--- a/src/shared/fileio-label.c
+++ b/src/shared/fileio-label.c
@@ -59,7 +59,7 @@ int fopen_temporary_label(const char *target,
                           const char *path, FILE **f, char **temp_path) {
         int r;
 
-        r = label_context_set("/etc/passwd", S_IFREG);
+        r = label_context_set(target, S_IFREG);
         if (r < 0)
                 return r;
 
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index d679394..b7c1609 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -195,8 +195,9 @@ static int load_group_database(void) {
         return 0;
 }
 
-static int make_backup(const char *x) {
-        _cleanup_close_ int src = -1, dst = -1;
+static int make_backup(const char *target, const char *x) {
+        _cleanup_close_ int src = -1;
+        _cleanup_fclose_ FILE *dst = NULL;
         char *backup, *temp;
         struct timespec ts[2];
         struct stat st;
@@ -213,30 +214,30 @@ static int make_backup(const char *x) {
         if (fstat(src, &st) < 0)
                 return -errno;
 
-        temp = strappenda(x, ".XXXXXX");
-        dst = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC|O_NOCTTY);
-        if (dst < 0)
-                return dst;
+        r = fopen_temporary_label(target, x, &dst, &temp);
+        if (r < 0)
+                return r;
 
-        r = copy_bytes(src, dst, (off_t) -1);
+        r = copy_bytes(src, fileno(dst), (off_t) -1);
         if (r < 0)
                 goto fail;
 
+        /* Don't fail on chmod() or chown(). If it stays owned by us
+         * and/or unreadable by others, then it isn't too bad... */
+
+        backup = strappenda(x, "-");
+
         /* Copy over the access mask */
-        if (fchmod(dst, st.st_mode & 07777) < 0) {
-                r = -errno;
-                goto fail;
-        }
+        if (fchmod(fileno(dst), st.st_mode & 07777) < 0)
+                log_warning("Failed to change mode on %s: %m", backup);
 
-        /* Don't fail on chmod(). If it stays owned by us, then it
-         * isn't too bad... */
-        fchown(dst, st.st_uid, st.st_gid);
+        if (fchown(fileno(dst), st.st_uid, st.st_gid)< 0)
+                log_warning("Failed to change ownership of %s: %m", backup);
 
         ts[0] = st.st_atim;
         ts[1] = st.st_mtim;
-        futimens(dst, ts);
+        futimens(fileno(dst), ts);
 
-        backup = strappenda(x, "-");
         if (rename(temp, backup) < 0)
                 goto fail;
 
@@ -469,13 +470,13 @@ static int write_files(void) {
 
         /* Make a backup of the old files */
         if (group && group_changed) {
-                r = make_backup(group_path);
+                r = make_backup("/etc/group", group_path);
                 if (r < 0)
                         goto finish;
         }
 
         if (passwd) {
-                r = make_backup(passwd_path);
+                r = make_backup("/etc/passwd", passwd_path);
                 if (r < 0)
                         goto finish;
         }
@@ -1493,9 +1494,11 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        label_init(NULL);
-
-        r = 0;
+        r = label_init(NULL);
+        if (r < 0) {
+                log_error("SELinux setup failed: %s", strerror(-r));
+                goto finish;
+        }
 
         if (optind < argc) {
                 int j;



More information about the systemd-commits mailing list