Merge v236 into tizen sandbox/adrians/upgrade-to-236
authorAdrian Szyndela <adrian.s@samsung.com>
Mon, 17 Feb 2020 13:12:39 +0000 (14:12 +0100)
committerAdrian Szyndela <adrian.s@samsung.com>
Wed, 26 Feb 2020 11:50:55 +0000 (12:50 +0100)
Change-Id: Id62f08b8ecf2a909a49e5f93b2f7594b3880ef44

166 files changed:
1  2 
.gitignore
TODO
man/sd_bus_creds_get_pid.xml
man/sd_bus_negotiate_fds.xml
man/systemd-notify.xml
man/systemd.exec.xml
man/systemd.service.xml
meson.build
meson_options.txt
packaging/systemd.spec
rules/50-udev-default.rules.in
rules/99-systemd.rules.in
rules/meson.build
shell-completion/zsh/_sd_unit_files
src/basic/cgroup-util.c
src/basic/clock-util.c
src/basic/clock-util.h
src/basic/def.h
src/basic/exit-status.c
src/basic/exit-status.h
src/basic/fd-util.c
src/basic/fs-util.c
src/basic/fs-util.h
src/basic/missing_syscall.h
src/basic/parse-util.c
src/basic/parse-util.h
src/basic/smack-util.c
src/basic/special.h
src/basic/stdio-util.h
src/basic/strv.h
src/basic/unit-def.c
src/basic/unit-def.h
src/busctl/busctl.c
src/core/busname.c
src/core/cgroup.c
src/core/dbus-execute.c
src/core/dbus-manager.c
src/core/dbus-manager.h
src/core/dbus.c
src/core/device.c
src/core/execute.c
src/core/execute.h
src/core/kmod-setup.c
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/core/load-fragment.h
src/core/macros.systemd.in
src/core/main.c
src/core/manager.c
src/core/manager.h
src/core/meson.build
src/core/mount-setup.c
src/core/org.freedesktop.systemd1.conf
src/core/service.c
src/core/socket.c
src/core/timer.c
src/core/unit.c
src/core/unit.h
src/dbus1-generator/dbus1-generator.c
src/journal/journald-kmsg.c
src/journal/journald-syslog.c
src/journal/test-journal-syslog.c
src/kernel-install/kernel-install
src/libsystemd-network/sd-radv.c
src/libsystemd/meson.build
src/libsystemd/sd-bus/bus-container.c
src/libsystemd/sd-bus/bus-container.h
src/libsystemd/sd-bus/bus-control.c
src/libsystemd/sd-bus/bus-control.h
src/libsystemd/sd-bus/bus-convenience.c
src/libsystemd/sd-bus/bus-dump.c
src/libsystemd/sd-bus/bus-dump.h
src/libsystemd/sd-bus/bus-internal.h
src/libsystemd/sd-bus/bus-kernel.c
src/libsystemd/sd-bus/bus-kernel.h
src/libsystemd/sd-bus/bus-message.c
src/libsystemd/sd-bus/bus-message.h
src/libsystemd/sd-bus/bus-slot.c
src/libsystemd/sd-bus/bus-socket.c
src/libsystemd/sd-bus/sd-bus.c
src/libsystemd/sd-bus/test-bus-benchmark.c
src/libsystemd/sd-bus/test-bus-zero-copy.c
src/libsystemd/sd-daemon/sd-daemon.c
src/locale/org.freedesktop.locale1.conf
src/login/70-power-switch.rules
src/login/logind-user.c
src/login/org.freedesktop.login1.conf
src/login/pam_systemd.c
src/notify/notify.c
src/nspawn/nspawn-mount.c
src/shared/bus-util.c
src/shared/bus-util.h
src/sysctl/sysctl.c
src/systemctl/systemctl.c
src/test/meson.build
src/test/test-fs-util.c
src/test/test-parse-util.c
src/test/test-stat-util.c
src/test/test-tables.c
src/udev/udev-builtin-hwdb.c
src/udev/udev-builtin-net_id.c
test/meson.build
test/test-functions
tmpfiles.d/meson.build
units/console-getty.service.m4.in
units/container-getty@.service.m4.in
units/debug-shell.service.in
units/emergency.service.in
units/getty@.service.m4
units/initrd-cleanup.service.in
units/initrd-parse-etc.service.in
units/initrd-switch-root.service.in
units/initrd-udevadm-cleanup-db.service.in
units/kmod-static-nodes.service.in
units/ldconfig.service
units/meson.build
units/org.freedesktop.import1.busname
units/quotaon.service.in
units/rescue.service.in
units/serial-getty@.service.m4
units/sysinit.target
units/systemd-ask-password-console.service.in
units/systemd-ask-password-wall.service.in
units/systemd-binfmt.service.in
units/systemd-exit.service.in
units/systemd-fsck-root.service.in
units/systemd-fsck@.service.in
units/systemd-halt.service.in
units/systemd-hibernate-resume@.service.in
units/systemd-hibernate.service.in
units/systemd-hostnamed.service.in
units/systemd-hwdb-update.service.in
units/systemd-hybrid-sleep.service.in
units/systemd-initctl.service.in
units/systemd-journal-catalog-update.service.in
units/systemd-journal-flush.service.in
units/systemd-journald.service.in
units/systemd-kexec.service.in
units/systemd-localed.service.in
units/systemd-logind.service.in
units/systemd-machine-id-commit.service.in
units/systemd-machined.service.in
units/systemd-modules-load.service.in
units/systemd-networkd.service.in
units/systemd-nspawn@.service.in
units/systemd-poweroff.service.in
units/systemd-quotacheck.service.in
units/systemd-reboot.service.in
units/systemd-remount-fs.service.in
units/systemd-resolved.service.in
units/systemd-suspend.service.in
units/systemd-sysctl.service.in
units/systemd-tmpfiles-clean.service.in
units/systemd-tmpfiles-setup-dev.service.in
units/systemd-tmpfiles-setup.service.in
units/systemd-udev-settle.service.in
units/systemd-udev-trigger.service.in
units/systemd-udevd.service.in
units/systemd-update-done.service.in
units/systemd-update-utmp-runlevel.service.in
units/systemd-update-utmp.service.in
units/systemd-user-sessions.service.in
units/systemd-vconsole-setup.service.in
units/tmp.mount.m4
units/user/meson.build
units/user@.service.in

diff --cc .gitignore
Simple merge
diff --cc TODO
Simple merge
  
      <para><function>sd_bus_creds_get_owner_uid()</function> will
      retrieve the numeric UID (user identifier) of the user who owns
-     the login session that the process is a part of. See
+     the user unit or login session that the process is a part of. See
      <citerefentry><refentrytitle>systemd-logind.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
-     For processes that are not part of a session, returns -ENXIO.
+     For processes that are not part of a user unit or session, returns
+     -ENXIO.
      </para>
  
 -    <para><function>sd_bus_creds_has_effective_cap()</function> will check whether the capability specified by
 -    <parameter>capability</parameter> was set in the effective capabilities mask. A positive return value means that it
 -    was set, zero means that it was not set, and a negative return value indicates an error. See <citerefentry
 -    project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry> and the
 -    <varname>AmbientCapabilities=</varname> and <varname>CapabilityBoundingSet=</varname> settings in
 +    <para><function>sd_bus_creds_has_effective_cap()</function> will
 +    check whether the capability specified by
 +    <parameter>capability</parameter> was set in the effective
 +    capabilities mask. A positive return value means that is was
 +    set, zero means that it was not set, and a negative return
 +    value indicates an error. See
 +    <citerefentry project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
 +    and <varname>Capabilities=</varname> and
 +    <varname>CapabilityBoundingSet=</varname> settings in
      <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
      </para>
  
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc meson.build
Simple merge
Simple merge
index b9c65cd,0000000..81d482c
mode 100644,000000..100644
--- /dev/null
@@@ -1,719 -1,0 +1,723 @@@
- Version:        235
 +# "enable foo" will turn into --enable-foo or --disable-foo
 +# depending "with_foo" macro
 +%define enable() %{expand:%%{?with_%{1}:--enable-%{1}}%%{!?with_%{1}:--disable-%{1}}}
 +
 +%define WITH_RANDOMSEED 0
 +%define WITH_BASH_COMPLETION 0
 +%define WITH_ZSH_COMPLETION 0
 +%define WITH_COREDUMP 0
 +%define WITH_BACKLIGHT 0
 +%define WITH_TIMEDATED 0
 +%define WITH_RFKILL 0
 +%define WITH_MACHINED 0
 +%define WITH_DOC 0
 +%define WITH_HOSTNAMED 0
 +
 +%define build_dir _build
 +%define dbuspolicydir %{_datadir}/dbus-1
 +
 +# The 'meson' macro is defined in rpm macros, but it uses features from rpm 4.15 ({shrink, set_build_flags)
 +# Below is a version suitable for our purposes
 +%define meson \
 +  CFLAGS="${CFLAGS:-%optflags}" \
 +  export CFLAGS \
 +  %{__meson} \\\
 +        --buildtype=plain \\\
 +        --prefix=%{_prefix} \\\
 +        --libdir=%{_libdir} \\\
 +        --libexecdir=%{_libexecdir} \\\
 +        --bindir=%{_bindir} \\\
 +        --sbindir=%{_sbindir} \\\
 +        --includedir=%{_includedir} \\\
 +        --datadir=%{_datadir} \\\
 +        --mandir=%{_mandir} \\\
 +        --infodir=%{_infodir} \\\
 +        --localedir=%{_datadir}/locale \\\
 +        --sysconfdir=%{_sysconfdir} \\\
 +        --localstatedir=%{_localstatedir} \\\
 +        --sharedstatedir=%{_sharedstatedir} \\\
 +        --wrap-mode=%{__meson_wrap_mode} \\\
 +              %{_vpath_builddir}
 +# Ninja macros below are defined for ninja in e.g. fedora distro, but
 +# so far they are not provided by Tizen's ninja package.
 +%define __ninja %{_bindir}/ninja
 +%define __ninja_common_opts -v %{?_smp_flags}
 +%define ninja_build \
 +              %{__ninja} %{__ninja_common_opts}
 +%define ninja_install \
 +              DESTDIR=%{buildroot} %{__ninja} install %{__ninja_common_opts}
 +
 +Name:           systemd
++Version:        236
 +Release:        0%{?release_flags}
 +# For a breakdown of the licensing, see README
 +License:        LGPL-2.1+ and GPL-2.0+
 +Summary:        A System and Service Manager
 +Url:            http://www.freedesktop.org/wiki/Software/systemd
 +Group:          Base/Startup
 +Source0:        https://github.com/systemd/systemd/archive/v%{version}.tar.gz
 +Source1:        pamconsole-tmp.conf
 +Source2:        %{name}-rpmlintrc
 +Source3:        test-runner.c
 +Source4:        wait-default-target.sh
 +Source5:        wait-delayed-target.sh
 +Source6:        org.tizen.system.conf
 +Source7:        sysctl-tizen-override.conf
 +Source1001:     systemd.manifest
 +BuildRequires:  gperf
 +BuildRequires:  intltool >= 0.40.0
 +BuildRequires:  libacl-devel
 +BuildRequires:  libblkid-devel >= 2.20
 +BuildRequires:  libcap-devel
 +BuildRequires:  libgcrypt-devel
 +BuildRequires:  libkmod-devel >= 14
 +%if %{?WITH_DOC}
 +BuildRequires:  xsltproc
 +BuildRequires:  docbook-xsl-stylesheets
 +%endif
 +BuildRequires:  pam-devel
 +BuildRequires:  pkgconfig
 +# BuildRequires:  pkgconfig(dbus-1)     # for remove circular dependency on OBS
 +BuildRequires:  pkgconfig(glib-2.0)
 +BuildRequires:  pkgconfig(liblzma)
 +BuildRequires:  pkgconfig(libkmod)
 +BuildRequires:  pkgconfig(mount)
 +BuildRequires:  meson
 +BuildRequires:  acl
 +BuildRequires:  python
 +# Requires:       dbus                  # for remove circular dependency on OBS
 +Requires:       filesystem
 +Requires(post): coreutils
 +Requires(pre):  coreutils
 +Requires(pre):  /usr/bin/getent
 +Requires(pre):  /usr/sbin/groupadd
 +Requires(post): %{_sbindir}/update-alternatives
 +Requires(preun): %{_sbindir}/update-alternatives
 +
 +Obsoletes:      SysVinit < 2.86-24
 +Obsoletes:      sysvinit < 2.86-24
 +Provides:       SysVinit = 2.86-24
 +Provides:       sysvinit = 2.86-24
 +Provides:       /bin/systemctl
 +Provides:       /sbin/shutdown
 +Provides:       udev = %{version}
 +Obsoletes:      udev < 183
 +
 +%description
 +systemd is a system and service manager for Linux, compatible with
 +SysV and LSB init scripts. systemd provides aggressive parallelization
 +capabilities, uses socket and D-Bus activation for starting services,
 +offers on-demand starting of daemons, keeps track of processes using
 +Linux cgroups, supports snapshotting and restoring of the system
 +state, maintains mount and automount points and implements an
 +elaborate transactional dependency-based service control logic. It can
 +work as a drop-in replacement for sysvinit.
 +
 +%package -n libsystemd
 +License:        LGPL-2.1+
 +Summary:        Systemd libraries
 +Group:          Base/Startup
 +Obsoletes:      libudev < 183
 +Provides:       libudev = %{version}
 +Obsoletes:      systemd < 185-4
 +Conflicts:      systemd < 185-4
 +
 +%description -n libsystemd
 +Libraries for systemd and udev, as well as the systemd PAM module.
 +
 +%package devel
 +License:        LGPL-2.1+
 +Summary:        Development headers for systemd
 +Requires:       %{name} = %{version}
 +Requires:             libsystemd = %{version}
 +Provides:       libudev-devel = %{version}
 +Obsoletes:      libudev-devel < 183
 +
 +%description devel
 +Development headers and auxiliary files for developing applications for systemd.
 +
 +%package analyze
 +License:        LGPL-2.1+
 +Summary:        Tool for processing systemd profiling information
 +Requires:       %{name} = %{version}
 +Obsoletes:      systemd < 38-5
 +
 +%description analyze
 +'systemd-analyze blame' lists which systemd unit needed how much time to finish
 +initialization at boot.
 +'systemd-analyze plot' renders an SVG visualizing the parallel start of units
 +at boot.
 +
 +%package tests
 +License:        LGPL-2.1+ and BSD-2-Clause
 +Summary:        Set of tests for sd-bus component
 +Requires:       %{name} = %{version}
 +
 +%description tests
 +This package is part of 'dbus-integratnion-tests' framework and contains set of tests
 +for sd-bus component (DBUS API C library).
 +
 +%package extension-kdbus
 +Summary:      Extension for systemd to support KDBUS in Tizen
 +Requires:     %{name} = %{version}-%{release}
 +
 +%description extension-kdbus
 +This modifies systemd to support KDBUS in Tizen.
 +
 +%prep
 +%setup -q
 +
 +%build
 +cp %{SOURCE1001} .
 +cp %{SOURCE3} .
 +
 +%define _vpath_srcdir .
 +%define _vpath_builddir %{build_dir}
 +%meson \
 +      -Dkdbus=true \
 +%if ! %{WITH_RANDOMSEED}
 +      -Drandomseed=false \
 +%endif
 +%if ! %{?WITH_COREDUMP}
 +      -Dcoredump=false \
 +%endif
 +%if ! %{?WITH_BACKLIGHT}
 +      -Dbacklight=false \
 +%endif
 +%if ! %{?WITH_TIMEDATED}
 +      -Dtimedated=false \
 +%endif
 +%if ! %{WITH_RFKILL}
 +      -Drfkill=false \
 +%endif
 +        -Dhwdb=false \
 +        -Dsysusers=false \
 +        -Dfirstboot=false \
 +        -Dpolkit=false \
 +        -Dtimesyncd=false \
 +        -Dresolve=false \
 +        -Dnetworkd=false \
 +%if ! %{?WITH_MACHINED}
 +        -Dmachined=false \
 +%endif
 +%if ! %{?WITH_HOSTNAMED}
 +        -Dhostnamed=false \
 +%endif
 +        -Dimportd=false \
 +              -Denvironment-d=false \
 +              -Dnss-systemd=false \
 +        -Dgcrypt=false \
 +%if ! %{?WITH_DOC}
 +        -Dman=false \
 +%endif
 +        -Drpmmacrosdir=%{_sysconfdir}/rpm/ \
 +        -Dsysvinit-path="" \
 +        -Dsysvrcnd-path="" \
 +        -Dsmack-run-label=System::Privileged \
 +              -Dinstall-tests=true \
 +              -Ddefault-hierarchy=legacy \
 +              -Db_pie=true
 +%meson_build
 +
 +# compile test-runner for 'dbus-integration-test' framework
 +%__cc %{_builddir}/%{name}-%{version}/test-runner.c -o %{_builddir}/%{name}-%{version}/systemd-tests
 +
 +%install
 +%meson_install
 +%find_lang %{name}
 +cat <<EOF >> systemd.lang
 +%lang(be) /usr/lib/systemd/catalog/systemd.be.catalog
 +%lang(be) /usr/lib/systemd/catalog/systemd.be@latin.catalog
 +%lang(bg) /usr/lib/systemd/catalog/systemd.bg.catalog
 +%lang(de) /usr/lib/systemd/catalog/systemd.de.catalog
 +%lang(fr) /usr/lib/systemd/catalog/systemd.fr.catalog
 +%lang(it) /usr/lib/systemd/catalog/systemd.it.catalog
 +%lang(pl) /usr/lib/systemd/catalog/systemd.pl.catalog
 +%lang(pt_BR) /usr/lib/systemd/catalog/systemd.pt_BR.catalog
 +%lang(ru) /usr/lib/systemd/catalog/systemd.ru.catalog
 +%lang(zh) /usr/lib/systemd/catalog/systemd.zh_CN.catalog
 +%lang(zh) /usr/lib/systemd/catalog/systemd.zh_TW.catalog
 +EOF
 +
 +# udev links
 +/usr/bin/mkdir -p %{buildroot}/%{_sbindir}
 +/usr/bin/ln -sf ../bin/udevadm %{buildroot}%{_sbindir}/udevadm
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/firmware/updates
 +
 +# Create SysV compatibility symlinks. systemctl/systemd are smart
 +# enough to detect in which way they are called.
 +/usr/bin/ln -s ../lib/systemd/systemd %{buildroot}%{_sbindir}/init
 +/usr/bin/ln -s ../lib/systemd/systemd %{buildroot}%{_bindir}/systemd
 +/usr/bin/ln -s ../bin/systemctl %{buildroot}%{_sbindir}/reboot
 +/usr/bin/ln -s ../bin/systemctl %{buildroot}%{_sbindir}/halt
 +/usr/bin/ln -s ../bin/systemctl %{buildroot}%{_sbindir}/poweroff
 +/usr/bin/ln -s ../bin/systemctl %{buildroot}%{_sbindir}/shutdown
 +/usr/bin/ln -s ../bin/systemctl %{buildroot}%{_sbindir}/telinit
 +/usr/bin/ln -s ../bin/systemctl %{buildroot}%{_sbindir}/runlevel
 +
 +# legacy links
 +/usr/bin/ln -s loginctl %{buildroot}%{_bindir}/systemd-loginctl
 +
 +# We create all wants links manually at installation time to make sure
 +# they are not owned and hence overriden by rpm after the used deleted
 +# them.
 +/usr/bin/rm -r %{buildroot}%{_sysconfdir}/systemd/system/*.target.wants
 +
 +# Make sure these directories are properly owned
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/basic.target.wants
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/default.target.wants
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/dbus.target.wants
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/syslog.target.wants
 +
 +# Make sure the user generators dir exists too
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system-generators
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/user-generators
 +
 +# Create new-style configuration files so that we can ghost-own them
 +/usr/bin/touch %{buildroot}%{_sysconfdir}/hostname
 +/usr/bin/touch %{buildroot}%{_sysconfdir}/vconsole.conf
 +/usr/bin/touch %{buildroot}%{_sysconfdir}/locale.conf
 +/usr/bin/touch %{buildroot}%{_sysconfdir}/machine-id
 +/usr/bin/touch %{buildroot}%{_sysconfdir}/machine-info
 +/usr/bin/touch %{buildroot}%{_sysconfdir}/timezone
 +
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system-preset/
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/user-preset/
 +
 +# Make sure the shutdown/sleep drop-in dirs exist
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system-shutdown/
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system-sleep/
 +
 +# Make sure the NTP units dir exists
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/ntp-units.d/
 +
 +# Install modprobe fragment
 +/usr/bin/mkdir -p %{buildroot}%{_sysconfdir}/modprobe.d/
 +
 +# Fix the dangling /var/lock -> /run/lock symlink
 +install -Dm644 tmpfiles.d/legacy.conf %{buildroot}%{_prefix}/lib/tmpfiles.d/legacy.conf
 +
 +install -m644 %{SOURCE1} %{buildroot}%{_prefix}/lib/tmpfiles.d/
 +
 +install -m 755 -d %{buildroot}/%{_prefix}/lib/systemd/system
 +
 +rm -rf %{buildroot}/%{_docdir}/%{name}
 +
 +# Allow replacing systemd-shutdown with tizen-specific variant
 +mv %{buildroot}%{_prefix}/lib/systemd/systemd-shutdown %{buildroot}%{_prefix}/lib/systemd/systemd-shutdown-original
 +
 +# Disable some useless services in Tizen
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/sysinit.target.wants/dev-hugepages.mount
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/sysinit.target.wants/sys-fs-fuse-connections.mount
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/sysinit.target.wants/systemd-binfmt.service
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/sysinit.target.wants/systemd-modules-load.service
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/sysinit.target.wants/systemd-ask-password-console.path
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/multi-user.target.wants/systemd-ask-password-wall.path
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/systemd-tmpfiles-clean.timer
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/systemd-tmpfiles-clean.service
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/timers.target.wants/systemd-tmpfiles-clean.timer
++rm -rf %{buildroot}/%{_prefix}/lib/systemd/user/systemd-tmpfiles-clean.timer
++rm -rf %{buildroot}/%{_prefix}/lib/systemd/user/systemd-tmpfiles-clean.service
++rm -rf %{buildroot}/%{_prefix}/lib/systemd/user/systemd-tmpfiles-setup.service
 +
 +# Exclude ELF binaries
 +rm -f %{buildroot}/%{_prefix}/lib/systemd/system-generators/systemd-debug-generator
 +rm -f %{buildroot}/%{_prefix}/lib/systemd/system-generators/systemd-efi-boot-generator
 +rm -f %{buildroot}/%{_prefix}/lib/systemd/system-generators/systemd-gpt-auto-generator
 +rm -f %{buildroot}/%{_prefix}/lib/systemd/system-generators/systemd-hibernate-resume-generator
 +
 +# Marker file for kdbus
 +touch %{buildroot}/%{_sysconfdir}/systemd/extension-kdbus
 +
 +# Prepare tests for 'dbus-integration-test' framework
 +install -D -m 755 %{_builddir}/%{name}-%{version}/systemd-tests %{buildroot}%{_prefix}/lib/dbus-tests/runner/systemd-tests
 +mkdir -p %{buildroot}%{_prefix}/lib/dbus-tests/test-suites/systemd-tests/
 +mv %{buildroot}%{_prefix}/lib/systemd/tests/test-bus-* %{buildroot}%{_prefix}/lib/dbus-tests/test-suites/systemd-tests/
 +
 +# Shell Completion
 +%if ! %{?WITH_BASH_COMPLETION}
 +rm -rf %{buildroot}/%{_datadir}/bash-completion/*
 +%endif
 +%if ! %{?WITH_ZSH_COMPLETION}
 +rm -rf %{buildroot}/%{_datadir}/zsh/site-functions/*
 +%endif
 +
 +mkdir -p %{buildroot}/%{_localstatedir}/log/journal
 +
 +ln -sf ./libsystemd.pc %{buildroot}%{_libdir}/pkgconfig/libsystemd-daemon.pc
 +ln -sf ./libsystemd.pc %{buildroot}%{_libdir}/pkgconfig/libsystemd-id128.pc
 +ln -sf ./libsystemd.pc %{buildroot}%{_libdir}/pkgconfig/libsystemd-journal.pc
 +ln -sf ./libsystemd.pc %{buildroot}%{_libdir}/pkgconfig/libsystemd-login.pc
 +
 +# Delayed target
 +install -m 0755 %{SOURCE4} %{buildroot}%{_bindir}/wait-default-target.sh
 +install -m 0755 %{SOURCE5} %{buildroot}%{_bindir}/wait-delayed-target.sh
 +install -m 0755 %{SOURCE6} %{buildroot}%{dbuspolicydir}/system.d/org.tizen.system.conf
 +
 +# Tizen sysctl values overriding default systemd values
 +install -m 0644 %{SOURCE7} %{buildroot}%{_sysconfdir}/sysctl.d/
 +
 +# end of install
 +%pre
 +/usr/bin/getent group cdrom >/dev/null 2>&1 || /usr/sbin/groupadd -r -g 11 cdrom >/dev/null 2>&1 || :
 +/usr/bin/getent group tape >/dev/null 2>&1 || /usr/sbin/groupadd -r -g 33 tape >/dev/null 2>&1 || :
 +/usr/bin/getent group dialout >/dev/null 2>&1 || /usr/sbin/groupadd -r -g 18 dialout >/dev/null 2>&1 || :
 +/usr/bin/getent group floppy >/dev/null 2>&1 || /usr/sbin/groupadd -r -g 19 floppy >/dev/null 2>&1 || :
 +/usr/bin/systemctl stop systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd.service >/dev/null 2>&1 || :
 +
 +# Rename configuration files that changed their names
 +/usr/bin/mv -n %{_sysconfdir}/systemd/systemd-logind.conf %{_sysconfdir}/systemd/logind.conf >/dev/null 2>&1 || :
 +/usr/bin/mv -n %{_sysconfdir}/systemd/systemd-journald.conf %{_sysconfdir}/systemd/journald.conf >/dev/null 2>&1 || :
 +
 +%post
 +/usr/bin/systemd-machine-id-setup > /dev/null 2>&1 || :
 +%if %{WITH_RANDOMSEED}
 +/usr/lib/systemd/systemd-random-seed save > /dev/null 2>&1 || :
 +%endif
 +/usr/bin/systemctl daemon-reexec > /dev/null 2>&1 || :
 +/usr/bin/systemctl start systemd-udevd.service >/dev/null 2>&1 || :
 +/usr/bin/mkdir -p /etc/systemd/network
 +/usr/bin/ln -sf /dev/null /etc/systemd/network/99-default.link
 +
 +# Set the smack label of executable binary tools
 +chsmack %{_bindir}/bootctl -a "System::Tools"
 +chsmack %{_bindir}/busctl -a "System::Tools"
 +chsmack %{_bindir}/kernel-install -a "System::Tools"
 +%if %{?WITH_MACHINED}
 +chsmack %{_bindir}/machinectl -a "System::Tools"
 +%endif
 +chsmack %{_bindir}/systemd-run -a "System::Tools"
 +%if %{?WITH_HOSTNAMED}
 +chsmack %{_bindir}/hostnamectl -a "System::Tools"
 +%endif
 +chsmack %{_bindir}/localectl -a "System::Tools"
 +%if %{?WITH_COREDUMP}
 +chsmack %{_bindir}/coredumpctl -a "System::Tools"
 +%endif
 +%if %{?WITH_TIMEDATED}
 +chsmack %{_bindir}/timedatectl -a "System::Tools"
 +%endif
 +chsmack %{_bindir}/systemd -a "System::Tools"
 +chsmack %{_bindir}/systemctl -a "System::Tools"
 +chsmack %{_bindir}/systemd-notify -a "System::Tools"
 +chsmack %{_bindir}/systemd-ask-password -a "System::Tools"
 +chsmack %{_bindir}/systemd-tty-ask-password-agent -a "System::Tools"
 +chsmack %{_bindir}/systemd-machine-id-setup -a "System::Tools"
 +chsmack %{_bindir}/systemd-socket-activate -a "System::Tools"
 +chsmack %{_bindir}/loginctl -a "System::Tools"
 +chsmack %{_bindir}/systemd-loginctl -a "System::Tools"
 +chsmack %{_bindir}/journalctl -a "System::Tools"
 +chsmack %{_bindir}/systemd-tmpfiles -a "System::Tools"
 +chsmack %{_bindir}/systemd-nspawn -a "System::Tools"
 +chsmack %{_bindir}/systemd-stdio-bridge -a "System::Tools"
 +chsmack %{_bindir}/systemd-cat -a "System::Tools"
 +chsmack %{_bindir}/systemd-cgls -a "System::Tools"
 +chsmack %{_bindir}/systemd-cgtop -a "System::Tools"
 +chsmack %{_bindir}/systemd-delta -a "System::Tools"
 +chsmack %{_bindir}/systemd-detect-virt -a "System::Tools"
 +chsmack %{_bindir}/systemd-inhibit -a "System::Tools"
 +chsmack %{_bindir}/udevadm -a "System::Tools"
 +chsmack %{_bindir}/systemd-escape -a "System::Tools"
 +chsmack %{_bindir}/systemd-path -a "System::Tools"
 +chsmack %{_prefix}/lib/systemd/* -a "System::Tools"
 +
 +%postun
 +if [ $1 -ge 1 ] ; then
 +        /usr/bin/systemctl daemon-reload > /dev/null 2>&1 || :
 +        /usr/bin/systemctl try-restart systemd-logind.service >/dev/null 2>&1 || :
 +fi
 +
 +%preun
 +if [ $1 -eq 0 ] ; then
 +        /usr/bin/systemctl disable \
 +                getty@.service \
 +                remote-fs.target \
 +                systemd-readahead-replay.service \
 +                systemd-readahead-collect.service >/dev/null 2>&1 || :
 +
 +        update-alternatives --remove systemd-shutdown %{_prefix}/lib/systemd/systemd-shutdown-original
 +fi
 +
 +%posttrans
 +# Update alternatives after the whole transaction is completed - this is
 +# necessary due to RPM ordering, which removes files from old package not
 +# provided by new package after regular post scripts are run.  Please refer
 +# to following guideliness for explanation:
 +#   https://fedoraproject.org/wiki/Packaging:Scriptlets#Ordering
 +if [ $1 -eq 0 ]; then
 +    update-alternatives --install %{_prefix}/lib/systemd/systemd-shutdown systemd-shutdown %{_prefix}/lib/systemd/systemd-shutdown-original 100 || :
 +fi
 +
 +%post -n libsystemd -p /sbin/ldconfig
 +%postun -n libsystemd  -p /sbin/ldconfig
 +
 +%lang_package
 +
 +%files
 +%manifest %{name}.manifest
 +%license LICENSE.LGPL2.1  LICENSE.GPL2
 +%config %{_sysconfdir}/pam.d/systemd-user
 +%{_bindir}/bootctl
 +%{_bindir}/busctl
 +%{_bindir}/kernel-install
 +%if %{?WITH_MACHINED}
 +%{_bindir}/machinectl
 +%endif
 +%{_bindir}/systemd-run
 +%dir %{_prefix}/lib/kernel
 +%dir %{_prefix}/lib/kernel/install.d
 +%{_prefix}/lib/kernel/install.d/50-depmod.install
 +%{_prefix}/lib/kernel/install.d/90-loaderentry.install
 +%if %{?WITH_HOSTNAMED}
 +%{_bindir}/hostnamectl
 +%endif
 +%{_bindir}/localectl
 +%if %{?WITH_COREDUMP}
 +%{_bindir}/coredumpctl
 +%endif
 +%if %{?WITH_TIMEDATED}
 +%{_bindir}/timedatectl
 +%endif
 +%dir %{_sysconfdir}/systemd
 +%dir %{_sysconfdir}/systemd/system
 +%dir %{_sysconfdir}/systemd/user
 +%dir %{_sysconfdir}/tmpfiles.d
 +%dir %{_sysconfdir}/sysctl.d
 +%dir %{_sysconfdir}/modules-load.d
 +%dir %{_sysconfdir}/binfmt.d
 +%if %{?WITH_BASH_COMPLETION}
 +%{_datadir}/bash-completion/*
 +%endif
 +%if %{?WITH_ZSH_COMPLETION}
 +%dir %{_datadir}/zsh/site-functions
 +%{_datadir}/zsh/site-functions/*
 +%endif
 +%dir %{_sysconfdir}/udev
 +%dir %{_sysconfdir}/udev/rules.d
 +%dir %{_prefix}/lib/systemd
 +%dir %{_prefix}/lib/systemd/system
 +%dir %{_prefix}/lib/systemd/system-generators
 +%dir %{_prefix}/lib/systemd/user-generators
 +%dir %{_prefix}/lib/systemd/system-preset
 +%dir %{_prefix}/lib/systemd/user-preset
 +%dir %{_prefix}/lib/systemd/system-shutdown
 +%dir %{_prefix}/lib/systemd/system-sleep
 +%dir %{_prefix}/lib/tmpfiles.d
 +%dir %{_prefix}/lib/sysctl.d
 +%dir %{_prefix}/lib/modules-load.d
 +%dir %{_prefix}/lib/binfmt.d
 +%dir %{_prefix}/lib/firmware
 +%dir %{_prefix}/lib/firmware/updates
 +%dir %{_datadir}/systemd
 +%config(noreplace) %{dbuspolicydir}/system.d/org.freedesktop.systemd1.conf
 +%if %{?WITH_HOSTNAMED}
 +%config(noreplace) %{dbuspolicydir}/system.d/org.freedesktop.hostname1.conf
 +%endif
 +%config(noreplace) %{dbuspolicydir}/system.d/org.freedesktop.login1.conf
 +%config(noreplace) %{dbuspolicydir}/system.d/org.freedesktop.locale1.conf
 +%if %{?WITH_TIMEDATED}
 +%config(noreplace) %{dbuspolicydir}/system.d/org.freedesktop.timedate1.conf
 +%endif
 +%if %{?WITH_MACHINED}
 +%config(noreplace) %{dbuspolicydir}/system.d/org.freedesktop.machine1.conf
 +%endif
 +%if %{?WITH_COREDUMP}
 +%config(noreplace) %{_sysconfdir}/systemd/coredump.conf
 +%else
 +%exclude %{_sysconfdir}/systemd/coredump.conf
 +%endif
 +%config(noreplace) %{_sysconfdir}/systemd/system.conf
 +%config(noreplace) %{_sysconfdir}/systemd/user.conf
 +%config(noreplace) %{_sysconfdir}/systemd/logind.conf
 +%config(noreplace) %{_sysconfdir}/systemd/journald.conf
 +%config(noreplace) %{_sysconfdir}/udev/udev.conf
 +%config(noreplace) %{_sysconfdir}/sysctl.d/sysctl-tizen-override.conf
 +%{_sysconfdir}/xdg/systemd
 +%ghost %config(noreplace) %{_sysconfdir}/hostname
 +%ghost %config(noreplace) %{_sysconfdir}/vconsole.conf
 +%ghost %config(noreplace) %{_sysconfdir}/locale.conf
 +%ghost %config(noreplace) %{_sysconfdir}/machine-id
 +%ghost %config(noreplace) %{_sysconfdir}/machine-info
 +%ghost %config(noreplace) %{_sysconfdir}/timezone
 +%exclude %{_sysconfdir}/X11/xinit/xinitrc.d/50-systemd-user.sh
 +%{_bindir}/systemd
 +%{_bindir}/systemctl
 +%{_bindir}/systemd-notify
 +%{_bindir}/systemd-ask-password
 +%{_bindir}/systemd-tty-ask-password-agent
 +%{_bindir}/systemd-machine-id-setup
 +%{_bindir}/systemd-socket-activate
 +%{_bindir}/loginctl
 +%{_bindir}/systemd-loginctl
 +%{_bindir}/journalctl
 +%{_bindir}/systemd-tmpfiles
 +%{_bindir}/systemd-nspawn
 +%{_bindir}/systemd-stdio-bridge
 +%{_bindir}/systemd-cat
 +%{_bindir}/systemd-cgls
 +%{_bindir}/systemd-cgtop
 +%{_bindir}/systemd-delta
 +%{_bindir}/systemd-detect-virt
 +%{_bindir}/systemd-inhibit
 +%{_bindir}/udevadm
 +%{_bindir}/systemd-escape
 +%{_bindir}/systemd-path
 +%{_bindir}/systemd-mount
 +%{_bindir}/systemd-umount
 +%{_prefix}/lib/sysctl.d/*.conf
 +%{_prefix}/lib/systemd/systemd
 +%{_prefix}/lib/systemd/system
 +
 +%dir %{_prefix}/lib/systemd/system/basic.target.wants
 +%dir %{_prefix}/lib/systemd/user
 +%dir %{_prefix}/lib/systemd/network
 +%dir %{_prefix}/lib/systemd/user/default.target.wants
 +%{_prefix}/lib/systemd/user/basic.target
 +%{_prefix}/lib/systemd/user/exit.target
 +%{_prefix}/lib/systemd/user/printer.target
 +%{_prefix}/lib/systemd/user/shutdown.target
 +%{_prefix}/lib/systemd/user/sockets.target
 +%{_prefix}/lib/systemd/user/sound.target
 +%{_prefix}/lib/systemd/user/systemd-exit.service
 +%{_prefix}/lib/systemd/user/paths.target
 +%{_prefix}/lib/systemd/user/smartcard.target
 +%{_prefix}/lib/systemd/user/timers.target
 +%{_prefix}/lib/systemd/user/default.target
 +%exclude %{_prefix}/lib/systemd/user/graphical-session.target
 +%exclude %{_prefix}/lib/systemd/user/graphical-session-pre.target
 +%{_prefix}/lib/systemd/network/99-default.link
 +%exclude %{_prefix}/lib/systemd/system-preset/90-systemd.preset
++%exclude %{_prefix}/lib/systemd/user-preset/90-systemd.preset
 +%{_prefix}/lib/systemd/user/delayed.target
 +%{_prefix}/lib/systemd/user/user-delayed-target-trigger.service
 +%{_prefix}/lib/systemd/user/default.target.wants/user-delayed-target-trigger.service
 +%{_prefix}/lib/systemd/user/user-default-target-done.service
 +%{_prefix}/lib/systemd/user/default.target.wants/user-default-target-done.service
 +%{_prefix}/lib/systemd/user/user-delayed-target-done.service
 +%{_prefix}/lib/systemd/user/delayed.target.wants/user-delayed-target-done.service
 +%{dbuspolicydir}/system.d/org.tizen.system.conf
 +%exclude %{_prefix}/lib/modprobe.d/systemd.conf
 +
 +%{_prefix}/lib/systemd/libsystemd-shared-%{version}.so
 +%{_prefix}/lib/systemd/systemd-*
 +%dir %{_prefix}/lib/systemd/catalog
 +%{_prefix}/lib/systemd/catalog/systemd.catalog
 +%{_prefix}/lib/udev
 +%{_prefix}/lib/systemd/system-generators/systemd-getty-generator
 +%{_prefix}/lib/systemd/system-generators/systemd-fstab-generator
 +%{_prefix}/lib/systemd/system-generators/systemd-system-update-generator
 +%{_prefix}/lib/tmpfiles.d/home.conf
 +%{_prefix}/lib/tmpfiles.d/journal-nocow.conf
 +%{_prefix}/lib/tmpfiles.d/legacy.conf
 +%{_prefix}/lib/tmpfiles.d/pamconsole-tmp.conf
 +%{_prefix}/lib/tmpfiles.d/systemd.conf
 +%{_prefix}/lib/tmpfiles.d/systemd-nologin.conf
 +%{_prefix}/lib/tmpfiles.d/systemd-nspawn.conf
 +%{_prefix}/lib/tmpfiles.d/tmp.conf
 +%{_prefix}/lib/tmpfiles.d/var.conf
 +%{_prefix}/lib/tmpfiles.d/x11.conf
 +%{_sbindir}/init
 +%{_sbindir}/reboot
 +%{_sbindir}/halt
 +%{_sbindir}/poweroff
 +%{_sbindir}/shutdown
 +%{_sbindir}/telinit
 +%{_sbindir}/runlevel
 +%{_sbindir}/udevadm
 +%{_datadir}/systemd/graphinfo.gvpr
 +%{_datadir}/systemd/kbd-model-map
 +%{_datadir}/systemd/language-fallback-map
 +%{_datadir}/dbus-1/services/org.freedesktop.systemd1.service
 +%{_datadir}/dbus-1/system-services/org.freedesktop.systemd1.service
 +%if %{?WITH_HOSTNAMED}
 +%{_datadir}/dbus-1/system-services/org.freedesktop.hostname1.service
 +%endif
 +%{_datadir}/dbus-1/system-services/org.freedesktop.login1.service
 +%{_datadir}/dbus-1/system-services/org.freedesktop.locale1.service
 +%if %{?WITH_TIMEDATED}
 +%{_datadir}/dbus-1/system-services/org.freedesktop.timedate1.service
 +%endif
 +%if %{?WITH_MACHINED}
 +%{_datadir}/dbus-1/system-services/org.freedesktop.machine1.service
 +%endif
 +%dir %{_datadir}/factory/
 +%dir %{_datadir}/factory/etc
 +%dir %{_datadir}/factory/etc/pam.d
 +%{_datadir}/factory/etc/nsswitch.conf
 +%{_datadir}/factory/etc/pam.d/other
 +%{_datadir}/factory/etc/pam.d/system-auth
 +
 +%{_localstatedir}/log/journal
 +
 +%{_bindir}/wait-default-target.sh
 +%{_bindir}/wait-delayed-target.sh
 +%exclude %{_prefix}/lib/systemd/system/runlevel0.target
 +%exclude %{_prefix}/lib/systemd/system/runlevel1.target
 +%exclude %{_prefix}/lib/systemd/system/runlevel2.target
 +%exclude %{_prefix}/lib/systemd/system/runlevel3.target
 +%exclude %{_prefix}/lib/systemd/system/runlevel4.target
 +%exclude %{_prefix}/lib/systemd/system/runlevel5.target
 +%exclude %{_prefix}/lib/systemd/system/runlevel6.target
 +
 +%files -n libsystemd
 +%manifest %{name}.manifest
 +%license LICENSE.LGPL2.1
 +%{_libdir}/security/pam_systemd.so
 +%{_libdir}/libsystemd.so.*
 +%{_libdir}/libudev.so.*
 +%{_libdir}/libnss_myhostname.so.2
 +%if %{?WITH_MACHINED}
 +%{_libdir}/libnss_mymachines.so.2
 +%endif
 +
 +%files extension-kdbus
 +%manifest %{name}.manifest
 +%license LICENSE.LGPL2.1  LICENSE.GPL2
 +%{_sysconfdir}/systemd/extension-kdbus
 +%{_prefix}/lib/systemd/user/busnames.target
 +%{_prefix}/lib/systemd/system-generators/systemd-dbus1-generator
 +%{_prefix}/lib/systemd/user-generators/systemd-dbus1-generator
 +
 +%files devel
 +%manifest %{name}.manifest
 +%{_libdir}/libudev.so
 +%{_libdir}/libsystemd.so
 +%dir %{_includedir}/systemd
 +%{_includedir}/systemd/sd-bus.h
 +%{_includedir}/systemd/sd-bus-protocol.h
 +%{_includedir}/systemd/sd-bus-vtable.h
 +%{_includedir}/systemd/sd-event.h
 +%{_includedir}/systemd/_sd-common.h
 +%{_includedir}/systemd/sd-daemon.h
 +%{_includedir}/systemd/sd-id128.h
 +%{_includedir}/systemd/sd-journal.h
 +%{_includedir}/systemd/sd-login.h
 +%{_includedir}/systemd/sd-messages.h
 +%{_includedir}/libudev.h
 +%{_libdir}/pkgconfig/libudev.pc
 +%{_libdir}/pkgconfig/libsystemd.pc
 +%{_datadir}/pkgconfig/systemd.pc
 +%{_datadir}/pkgconfig/udev.pc
 +%{_libdir}/pkgconfig/libsystemd-daemon.pc
 +%{_libdir}/pkgconfig/libsystemd-id128.pc
 +%{_libdir}/pkgconfig/libsystemd-journal.pc
 +%{_libdir}/pkgconfig/libsystemd-login.pc
 +%{_sysconfdir}/rpm/macros.systemd
 +
 +%files analyze
 +%manifest %{name}.manifest
 +%license LICENSE.LGPL2.1
 +%{_bindir}/systemd-analyze
 +
 +%files tests
 +%manifest %{name}.manifest
 +%{_prefix}/lib/dbus-tests/test-suites/systemd-tests/
 +%{_prefix}/lib/dbus-tests/runner/systemd-tests
 +%{_prefix}/lib/systemd/tests/
 +
 +%if %{?WITH_DOC}
 +%docs_package
 +%else
 +%exclude %{_docdir}
 +%exclude %{_datadir}/doc/systemd
 +%endif
Simple merge
Simple merge
@@@ -1,5 -1,21 +1,22 @@@
+ # SPDX-License-Identifier: LGPL-2.1+
+ #
+ # Copyright 2017 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/>.
  rules = files('''
 +        55-udev-smack-default.rules
          60-block.rules
          60-cdrom_id.rules
          60-drm.rules
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc src/basic/def.h
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -772,14 -735,8 +772,14 @@@ int chase_symlinks(const char *path, co
  
                  if (fstat(child, &st) < 0)
                          return -errno;
 +                if ((flags & CHASE_SAFE) &&
 +                    !safe_transition(&previous_stat, &st))
 +                        return -EPERM;
 +
 +                previous_stat = st;
 +
                  if ((flags & CHASE_NO_AUTOFS) &&
-                     fd_check_fstype(child, AUTOFS_SUPER_MAGIC) > 0)
+                     fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0)
                          return -EREMOTE;
  
                  if (S_ISLNK(st.st_mode)) {
Simple merge
@@@ -340,10 -318,10 +341,12 @@@ static inline ssize_t missing_copy_file
          return -1;
  #  endif
  }
 +
 +#  define copy_file_range missing_copy_file_range
  #endif
  
+ /* ======================================================================= */
  #if !HAVE_BPF
  #  ifndef __NR_bpf
  #    if defined __i386__
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,387533f..6a1fc95
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,290 +1,305 @@@
+ /* SPDX-License-Identifier: LGPL-2.1+ */
+ /***
+   This file is part of systemd.
+   Copyright 2010 Lennart Poettering
+   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 "alloc-util.h"
+ #include "bus-label.h"
+ #include "string-table.h"
+ #include "unit-def.h"
+ #include "unit-name.h"
+ char *unit_dbus_path_from_name(const char *name) {
+         _cleanup_free_ char *e = NULL;
+         assert(name);
+         e = bus_label_escape(name);
+         if (!e)
+                 return NULL;
+         return strappend("/org/freedesktop/systemd1/unit/", e);
+ }
+ int unit_name_from_dbus_path(const char *path, char **name) {
+         const char *e;
+         char *n;
+         e = startswith(path, "/org/freedesktop/systemd1/unit/");
+         if (!e)
+                 return -EINVAL;
+         n = bus_label_unescape(e);
+         if (!n)
+                 return -ENOMEM;
+         *name = n;
+         return 0;
+ }
+ const char* unit_dbus_interface_from_type(UnitType t) {
+         static const char *const table[_UNIT_TYPE_MAX] = {
+                 [UNIT_SERVICE] = "org.freedesktop.systemd1.Service",
+                 [UNIT_SOCKET] = "org.freedesktop.systemd1.Socket",
++                [UNIT_BUSNAME] = "org.freedesktop.systemd1.BusName",
+                 [UNIT_TARGET] = "org.freedesktop.systemd1.Target",
+                 [UNIT_DEVICE] = "org.freedesktop.systemd1.Device",
+                 [UNIT_MOUNT] = "org.freedesktop.systemd1.Mount",
+                 [UNIT_AUTOMOUNT] = "org.freedesktop.systemd1.Automount",
+                 [UNIT_SWAP] = "org.freedesktop.systemd1.Swap",
+                 [UNIT_TIMER] = "org.freedesktop.systemd1.Timer",
+                 [UNIT_PATH] = "org.freedesktop.systemd1.Path",
+                 [UNIT_SLICE] = "org.freedesktop.systemd1.Slice",
+                 [UNIT_SCOPE] = "org.freedesktop.systemd1.Scope",
+         };
+         if (t < 0)
+                 return NULL;
+         if (t >= _UNIT_TYPE_MAX)
+                 return NULL;
+         return table[t];
+ }
+ const char *unit_dbus_interface_from_name(const char *name) {
+         UnitType t;
+         t = unit_name_to_type(name);
+         if (t < 0)
+                 return NULL;
+         return unit_dbus_interface_from_type(t);
+ }
+ static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
+         [UNIT_SERVICE] = "service",
+         [UNIT_SOCKET] = "socket",
++        [UNIT_BUSNAME] = "busname",
+         [UNIT_TARGET] = "target",
+         [UNIT_DEVICE] = "device",
+         [UNIT_MOUNT] = "mount",
+         [UNIT_AUTOMOUNT] = "automount",
+         [UNIT_SWAP] = "swap",
+         [UNIT_TIMER] = "timer",
+         [UNIT_PATH] = "path",
+         [UNIT_SLICE] = "slice",
+         [UNIT_SCOPE] = "scope",
+ };
+ DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType);
+ static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
+         [UNIT_STUB] = "stub",
+         [UNIT_LOADED] = "loaded",
+         [UNIT_NOT_FOUND] = "not-found",
+         [UNIT_ERROR] = "error",
+         [UNIT_MERGED] = "merged",
+         [UNIT_MASKED] = "masked"
+ };
+ DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
+ static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
+         [UNIT_ACTIVE] = "active",
+         [UNIT_RELOADING] = "reloading",
+         [UNIT_INACTIVE] = "inactive",
+         [UNIT_FAILED] = "failed",
+         [UNIT_ACTIVATING] = "activating",
+         [UNIT_DEACTIVATING] = "deactivating"
+ };
+ DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
+ static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
+         [AUTOMOUNT_DEAD] = "dead",
+         [AUTOMOUNT_WAITING] = "waiting",
+         [AUTOMOUNT_RUNNING] = "running",
+         [AUTOMOUNT_FAILED] = "failed"
+ };
+ DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
++static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
++        [BUSNAME_DEAD] = "dead",
++        [BUSNAME_MAKING] = "making",
++        [BUSNAME_REGISTERED] = "registered",
++        [BUSNAME_LISTENING] = "listening",
++        [BUSNAME_RUNNING] = "running",
++        [BUSNAME_SIGTERM] = "sigterm",
++        [BUSNAME_SIGKILL] = "sigkill",
++        [BUSNAME_FAILED] = "failed",
++};
++
++DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
++
+ static const char* const device_state_table[_DEVICE_STATE_MAX] = {
+         [DEVICE_DEAD] = "dead",
+         [DEVICE_TENTATIVE] = "tentative",
+         [DEVICE_PLUGGED] = "plugged",
+ };
+ DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
+ static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
+         [MOUNT_DEAD] = "dead",
+         [MOUNT_MOUNTING] = "mounting",
+         [MOUNT_MOUNTING_DONE] = "mounting-done",
+         [MOUNT_MOUNTED] = "mounted",
+         [MOUNT_REMOUNTING] = "remounting",
+         [MOUNT_UNMOUNTING] = "unmounting",
+         [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
+         [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
+         [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
+         [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
+         [MOUNT_FAILED] = "failed"
+ };
+ DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
+ static const char* const path_state_table[_PATH_STATE_MAX] = {
+         [PATH_DEAD] = "dead",
+         [PATH_WAITING] = "waiting",
+         [PATH_RUNNING] = "running",
+         [PATH_FAILED] = "failed"
+ };
+ DEFINE_STRING_TABLE_LOOKUP(path_state, PathState);
+ static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
+         [SCOPE_DEAD] = "dead",
+         [SCOPE_RUNNING] = "running",
+         [SCOPE_ABANDONED] = "abandoned",
+         [SCOPE_STOP_SIGTERM] = "stop-sigterm",
+         [SCOPE_STOP_SIGKILL] = "stop-sigkill",
+         [SCOPE_FAILED] = "failed",
+ };
+ DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
+ static const char* const service_state_table[_SERVICE_STATE_MAX] = {
+         [SERVICE_DEAD] = "dead",
+         [SERVICE_START_PRE] = "start-pre",
+         [SERVICE_START] = "start",
+         [SERVICE_START_POST] = "start-post",
+         [SERVICE_RUNNING] = "running",
+         [SERVICE_EXITED] = "exited",
+         [SERVICE_RELOAD] = "reload",
+         [SERVICE_STOP] = "stop",
+         [SERVICE_STOP_SIGABRT] = "stop-sigabrt",
+         [SERVICE_STOP_SIGTERM] = "stop-sigterm",
+         [SERVICE_STOP_SIGKILL] = "stop-sigkill",
+         [SERVICE_STOP_POST] = "stop-post",
+         [SERVICE_FINAL_SIGTERM] = "final-sigterm",
+         [SERVICE_FINAL_SIGKILL] = "final-sigkill",
+         [SERVICE_FAILED] = "failed",
+         [SERVICE_AUTO_RESTART] = "auto-restart",
+ };
+ DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
+ static const char* const slice_state_table[_SLICE_STATE_MAX] = {
+         [SLICE_DEAD] = "dead",
+         [SLICE_ACTIVE] = "active"
+ };
+ DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
+ static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
+         [SOCKET_DEAD] = "dead",
+         [SOCKET_START_PRE] = "start-pre",
+         [SOCKET_START_CHOWN] = "start-chown",
+         [SOCKET_START_POST] = "start-post",
+         [SOCKET_LISTENING] = "listening",
+         [SOCKET_RUNNING] = "running",
+         [SOCKET_STOP_PRE] = "stop-pre",
+         [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm",
+         [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill",
+         [SOCKET_STOP_POST] = "stop-post",
+         [SOCKET_FINAL_SIGTERM] = "final-sigterm",
+         [SOCKET_FINAL_SIGKILL] = "final-sigkill",
+         [SOCKET_FAILED] = "failed"
+ };
+ DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
+ static const char* const swap_state_table[_SWAP_STATE_MAX] = {
+         [SWAP_DEAD] = "dead",
+         [SWAP_ACTIVATING] = "activating",
+         [SWAP_ACTIVATING_DONE] = "activating-done",
+         [SWAP_ACTIVE] = "active",
+         [SWAP_DEACTIVATING] = "deactivating",
+         [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
+         [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
+         [SWAP_FAILED] = "failed"
+ };
+ DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
+ static const char* const target_state_table[_TARGET_STATE_MAX] = {
+         [TARGET_DEAD] = "dead",
+         [TARGET_ACTIVE] = "active"
+ };
+ DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
+ static const char* const timer_state_table[_TIMER_STATE_MAX] = {
+         [TIMER_DEAD] = "dead",
+         [TIMER_WAITING] = "waiting",
+         [TIMER_RUNNING] = "running",
+         [TIMER_ELAPSED] = "elapsed",
+         [TIMER_FAILED] = "failed"
+ };
+ DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
+ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
+         [UNIT_REQUIRES] = "Requires",
+         [UNIT_REQUISITE] = "Requisite",
+         [UNIT_WANTS] = "Wants",
+         [UNIT_BINDS_TO] = "BindsTo",
+         [UNIT_PART_OF] = "PartOf",
+         [UNIT_REQUIRED_BY] = "RequiredBy",
+         [UNIT_REQUISITE_OF] = "RequisiteOf",
+         [UNIT_WANTED_BY] = "WantedBy",
+         [UNIT_BOUND_BY] = "BoundBy",
+         [UNIT_CONSISTS_OF] = "ConsistsOf",
+         [UNIT_CONFLICTS] = "Conflicts",
+         [UNIT_CONFLICTED_BY] = "ConflictedBy",
+         [UNIT_BEFORE] = "Before",
+         [UNIT_AFTER] = "After",
+         [UNIT_ON_FAILURE] = "OnFailure",
+         [UNIT_TRIGGERS] = "Triggers",
+         [UNIT_TRIGGERED_BY] = "TriggeredBy",
+         [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo",
+         [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom",
+         [UNIT_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf",
+         [UNIT_REFERENCES] = "References",
+         [UNIT_REFERENCED_BY] = "ReferencedBy",
+ };
+ DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);
+ static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = {
+         [NOTIFY_NONE] = "none",
+         [NOTIFY_MAIN] = "main",
+         [NOTIFY_EXEC] = "exec",
+         [NOTIFY_ALL] = "all"
+ };
+ DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess);
index 0000000,c142e06..e7aacbd
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,302 +1,319 @@@
+ /* SPDX-License-Identifier: LGPL-2.1+ */
+ #pragma once
+ /***
+   This file is part of systemd.
+   Copyright 2010 Lennart Poettering
+   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 "macro.h"
+ typedef enum UnitType {
+         UNIT_SERVICE = 0,
+         UNIT_SOCKET,
++        UNIT_BUSNAME,
+         UNIT_TARGET,
+         UNIT_DEVICE,
+         UNIT_MOUNT,
+         UNIT_AUTOMOUNT,
+         UNIT_SWAP,
+         UNIT_TIMER,
+         UNIT_PATH,
+         UNIT_SLICE,
+         UNIT_SCOPE,
+         _UNIT_TYPE_MAX,
+         _UNIT_TYPE_INVALID = -1
+ } UnitType;
+ typedef enum UnitLoadState {
+         UNIT_STUB = 0,
+         UNIT_LOADED,
+         UNIT_NOT_FOUND,
+         UNIT_ERROR,
+         UNIT_MERGED,
+         UNIT_MASKED,
+         _UNIT_LOAD_STATE_MAX,
+         _UNIT_LOAD_STATE_INVALID = -1
+ } UnitLoadState;
+ typedef enum UnitActiveState {
+         UNIT_ACTIVE,
+         UNIT_RELOADING,
+         UNIT_INACTIVE,
+         UNIT_FAILED,
+         UNIT_ACTIVATING,
+         UNIT_DEACTIVATING,
+         _UNIT_ACTIVE_STATE_MAX,
+         _UNIT_ACTIVE_STATE_INVALID = -1
+ } UnitActiveState;
+ typedef enum AutomountState {
+         AUTOMOUNT_DEAD,
+         AUTOMOUNT_WAITING,
+         AUTOMOUNT_RUNNING,
+         AUTOMOUNT_FAILED,
+         _AUTOMOUNT_STATE_MAX,
+         _AUTOMOUNT_STATE_INVALID = -1
+ } AutomountState;
++typedef enum BusNameState {
++        BUSNAME_DEAD,
++        BUSNAME_MAKING,
++        BUSNAME_REGISTERED,
++        BUSNAME_LISTENING,
++        BUSNAME_RUNNING,
++        BUSNAME_SIGTERM,
++        BUSNAME_SIGKILL,
++        BUSNAME_FAILED,
++        _BUSNAME_STATE_MAX,
++        _BUSNAME_STATE_INVALID = -1
++} BusNameState;
++
+ /* We simply watch devices, we cannot plug/unplug them. That
+  * simplifies the state engine greatly */
+ typedef enum DeviceState {
+         DEVICE_DEAD,
+         DEVICE_TENTATIVE, /* mounted or swapped, but not (yet) announced by udev */
+         DEVICE_PLUGGED,   /* announced by udev */
+         _DEVICE_STATE_MAX,
+         _DEVICE_STATE_INVALID = -1
+ } DeviceState;
+ typedef enum MountState {
+         MOUNT_DEAD,
+         MOUNT_MOUNTING,               /* /usr/bin/mount is running, but the mount is not done yet. */
+         MOUNT_MOUNTING_DONE,          /* /usr/bin/mount is running, and the mount is done. */
+         MOUNT_MOUNTED,
+         MOUNT_REMOUNTING,
+         MOUNT_UNMOUNTING,
+         MOUNT_REMOUNTING_SIGTERM,
+         MOUNT_REMOUNTING_SIGKILL,
+         MOUNT_UNMOUNTING_SIGTERM,
+         MOUNT_UNMOUNTING_SIGKILL,
+         MOUNT_FAILED,
+         _MOUNT_STATE_MAX,
+         _MOUNT_STATE_INVALID = -1
+ } MountState;
+ typedef enum PathState {
+         PATH_DEAD,
+         PATH_WAITING,
+         PATH_RUNNING,
+         PATH_FAILED,
+         _PATH_STATE_MAX,
+         _PATH_STATE_INVALID = -1
+ } PathState;
+ typedef enum ScopeState {
+         SCOPE_DEAD,
+         SCOPE_RUNNING,
+         SCOPE_ABANDONED,
+         SCOPE_STOP_SIGTERM,
+         SCOPE_STOP_SIGKILL,
+         SCOPE_FAILED,
+         _SCOPE_STATE_MAX,
+         _SCOPE_STATE_INVALID = -1
+ } ScopeState;
+ typedef enum ServiceState {
+         SERVICE_DEAD,
+         SERVICE_START_PRE,
+         SERVICE_START,
+         SERVICE_START_POST,
+         SERVICE_RUNNING,
+         SERVICE_EXITED,            /* Nothing is running anymore, but RemainAfterExit is true hence this is OK */
+         SERVICE_RELOAD,
+         SERVICE_STOP,              /* No STOP_PRE state, instead just register multiple STOP executables */
+         SERVICE_STOP_SIGABRT,      /* Watchdog timeout */
+         SERVICE_STOP_SIGTERM,
+         SERVICE_STOP_SIGKILL,
+         SERVICE_STOP_POST,
+         SERVICE_FINAL_SIGTERM,     /* In case the STOP_POST executable hangs, we shoot that down, too */
+         SERVICE_FINAL_SIGKILL,
+         SERVICE_FAILED,
+         SERVICE_AUTO_RESTART,
+         _SERVICE_STATE_MAX,
+         _SERVICE_STATE_INVALID = -1
+ } ServiceState;
+ typedef enum SliceState {
+         SLICE_DEAD,
+         SLICE_ACTIVE,
+         _SLICE_STATE_MAX,
+         _SLICE_STATE_INVALID = -1
+ } SliceState;
+ typedef enum SocketState {
+         SOCKET_DEAD,
+         SOCKET_START_PRE,
+         SOCKET_START_CHOWN,
+         SOCKET_START_POST,
+         SOCKET_LISTENING,
+         SOCKET_RUNNING,
+         SOCKET_STOP_PRE,
+         SOCKET_STOP_PRE_SIGTERM,
+         SOCKET_STOP_PRE_SIGKILL,
+         SOCKET_STOP_POST,
+         SOCKET_FINAL_SIGTERM,
+         SOCKET_FINAL_SIGKILL,
+         SOCKET_FAILED,
+         _SOCKET_STATE_MAX,
+         _SOCKET_STATE_INVALID = -1
+ } SocketState;
+ typedef enum SwapState {
+         SWAP_DEAD,
+         SWAP_ACTIVATING,               /* /sbin/swapon is running, but the swap not yet enabled. */
+         SWAP_ACTIVATING_DONE,          /* /sbin/swapon is running, and the swap is done. */
+         SWAP_ACTIVE,
+         SWAP_DEACTIVATING,
+         SWAP_DEACTIVATING_SIGTERM,
+         SWAP_DEACTIVATING_SIGKILL,
+         SWAP_FAILED,
+         _SWAP_STATE_MAX,
+         _SWAP_STATE_INVALID = -1
+ } SwapState;
+ typedef enum TargetState {
+         TARGET_DEAD,
+         TARGET_ACTIVE,
+         _TARGET_STATE_MAX,
+         _TARGET_STATE_INVALID = -1
+ } TargetState;
+ typedef enum TimerState {
+         TIMER_DEAD,
+         TIMER_WAITING,
+         TIMER_RUNNING,
+         TIMER_ELAPSED,
+         TIMER_FAILED,
+         _TIMER_STATE_MAX,
+         _TIMER_STATE_INVALID = -1
+ } TimerState;
+ typedef enum UnitDependency {
+         /* Positive dependencies */
+         UNIT_REQUIRES,
+         UNIT_REQUISITE,
+         UNIT_WANTS,
+         UNIT_BINDS_TO,
+         UNIT_PART_OF,
+         /* Inverse of the above */
+         UNIT_REQUIRED_BY,             /* inverse of 'requires' is 'required_by' */
+         UNIT_REQUISITE_OF,            /* inverse of 'requisite' is 'requisite_of' */
+         UNIT_WANTED_BY,               /* inverse of 'wants' */
+         UNIT_BOUND_BY,                /* inverse of 'binds_to' */
+         UNIT_CONSISTS_OF,             /* inverse of 'part_of' */
+         /* Negative dependencies */
+         UNIT_CONFLICTS,               /* inverse of 'conflicts' is 'conflicted_by' */
+         UNIT_CONFLICTED_BY,
+         /* Order */
+         UNIT_BEFORE,                  /* inverse of 'before' is 'after' and vice versa */
+         UNIT_AFTER,
+         /* On Failure */
+         UNIT_ON_FAILURE,
+         /* Triggers (i.e. a socket triggers a service) */
+         UNIT_TRIGGERS,
+         UNIT_TRIGGERED_BY,
+         /* Propagate reloads */
+         UNIT_PROPAGATES_RELOAD_TO,
+         UNIT_RELOAD_PROPAGATED_FROM,
+         /* Joins namespace of */
+         UNIT_JOINS_NAMESPACE_OF,
+         /* Reference information for GC logic */
+         UNIT_REFERENCES,              /* Inverse of 'references' is 'referenced_by' */
+         UNIT_REFERENCED_BY,
+         _UNIT_DEPENDENCY_MAX,
+         _UNIT_DEPENDENCY_INVALID = -1
+ } UnitDependency;
+ typedef enum NotifyAccess {
+         NOTIFY_NONE,
+         NOTIFY_ALL,
+         NOTIFY_MAIN,
+         NOTIFY_EXEC,
+         _NOTIFY_ACCESS_MAX,
+         _NOTIFY_ACCESS_INVALID = -1
+ } NotifyAccess;
+ char *unit_dbus_path_from_name(const char *name);
+ int unit_name_from_dbus_path(const char *path, char **name);
+ const char* unit_dbus_interface_from_type(UnitType t);
+ const char *unit_dbus_interface_from_name(const char *name);
+ const char *unit_type_to_string(UnitType i) _const_;
+ UnitType unit_type_from_string(const char *s) _pure_;
+ const char *unit_load_state_to_string(UnitLoadState i) _const_;
+ UnitLoadState unit_load_state_from_string(const char *s) _pure_;
+ const char *unit_active_state_to_string(UnitActiveState i) _const_;
+ UnitActiveState unit_active_state_from_string(const char *s) _pure_;
+ const char* automount_state_to_string(AutomountState i) _const_;
+ AutomountState automount_state_from_string(const char *s) _pure_;
++const char* busname_state_to_string(BusNameState i) _const_;
++BusNameState busname_state_from_string(const char *s) _pure_;
++
+ const char* device_state_to_string(DeviceState i) _const_;
+ DeviceState device_state_from_string(const char *s) _pure_;
+ const char* mount_state_to_string(MountState i) _const_;
+ MountState mount_state_from_string(const char *s) _pure_;
+ const char* path_state_to_string(PathState i) _const_;
+ PathState path_state_from_string(const char *s) _pure_;
+ const char* scope_state_to_string(ScopeState i) _const_;
+ ScopeState scope_state_from_string(const char *s) _pure_;
+ const char* service_state_to_string(ServiceState i) _const_;
+ ServiceState service_state_from_string(const char *s) _pure_;
+ const char* slice_state_to_string(SliceState i) _const_;
+ SliceState slice_state_from_string(const char *s) _pure_;
+ const char* socket_state_to_string(SocketState i) _const_;
+ SocketState socket_state_from_string(const char *s) _pure_;
+ const char* swap_state_to_string(SwapState i) _const_;
+ SwapState swap_state_from_string(const char *s) _pure_;
+ const char* target_state_to_string(TargetState i) _const_;
+ TargetState target_state_from_string(const char *s) _pure_;
+ const char *timer_state_to_string(TimerState i) _const_;
+ TimerState timer_state_from_string(const char *s) _pure_;
+ const char *unit_dependency_to_string(UnitDependency i) _const_;
+ UnitDependency unit_dependency_from_string(const char *s) _pure_;
+ const char* notify_access_to_string(NotifyAccess i) _const_;
+ NotifyAccess notify_access_from_string(const char *s) _pure_;
  ***/
  
  #include <getopt.h>
+ #include <stdio_ext.h>
 +#include <hashmap.h>
 +
  #include "sd-bus.h"
  
  #include "alloc-util.h"
index 0826f2f,0000000..e06f2f4
mode 100644,000000..100644
--- /dev/null
@@@ -1,1081 -1,0 +1,1082 @@@
-         r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
 +/***
 +  This file is part of systemd.
 +
 +  Copyright 2013 Lennart Poettering
 +
 +  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 <linux/kdbus.h>
 +#include <sys/mman.h>
 +
 +#include "alloc-util.h"
 +#include "bus-internal.h"
 +#include "bus-kernel.h"
 +#include "bus-policy.h"
 +#include "bus-util.h"
 +#include "busname.h"
 +#include "dbus-busname.h"
 +#include "fd-util.h"
 +#include "format-util.h"
 +#include "parse-util.h"
 +#include "process-util.h"
 +#include "service.h"
 +#include "signal-util.h"
 +#include "special.h"
 +#include "string-table.h"
 +#include "string-util.h"
 +
 +static const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
 +        [BUSNAME_DEAD] = UNIT_INACTIVE,
 +        [BUSNAME_MAKING] = UNIT_ACTIVATING,
 +        [BUSNAME_REGISTERED] = UNIT_ACTIVE,
 +        [BUSNAME_LISTENING] = UNIT_ACTIVE,
 +        [BUSNAME_RUNNING] = UNIT_ACTIVE,
 +        [BUSNAME_SIGTERM] = UNIT_DEACTIVATING,
 +        [BUSNAME_SIGKILL] = UNIT_DEACTIVATING,
 +        [BUSNAME_FAILED] = UNIT_FAILED
 +};
 +
 +static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
 +static int busname_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
 +
 +static void busname_init(Unit *u) {
 +        BusName *n = BUSNAME(u);
 +
 +        assert(u);
 +        assert(u->load_state == UNIT_STUB);
 +
 +        n->starter_fd = -1;
 +        n->accept_fd = true;
 +        n->activating = true;
 +
 +        n->timeout_usec = u->manager->default_timeout_start_usec;
 +}
 +
 +static void busname_unwatch_control_pid(BusName *n) {
 +        assert(n);
 +
 +        if (n->control_pid <= 0)
 +                return;
 +
 +        unit_unwatch_pid(UNIT(n), n->control_pid);
 +        n->control_pid = 0;
 +}
 +
 +static void busname_free_policy(BusName *n) {
 +        BusNamePolicy *p;
 +
 +        assert(n);
 +
 +        while ((p = n->policy)) {
 +                LIST_REMOVE(policy, n->policy, p);
 +
 +                free(p->name);
 +                free(p);
 +        }
 +}
 +
 +static void busname_close_fd(BusName *n) {
 +        assert(n);
 +
 +        n->starter_event_source = sd_event_source_unref(n->starter_event_source);
 +        n->starter_fd = safe_close(n->starter_fd);
 +}
 +
 +static void busname_done(Unit *u) {
 +        BusName *n = BUSNAME(u);
 +
 +        assert(n);
 +
 +        n->name = mfree(n->name);
 +
 +        busname_free_policy(n);
 +        busname_unwatch_control_pid(n);
 +        busname_close_fd(n);
 +
 +        unit_ref_unset(&n->service);
 +
 +        n->timer_event_source = sd_event_source_unref(n->timer_event_source);
 +}
 +
 +static int busname_arm_timer(BusName *n, usec_t usec) {
 +        int r;
 +
 +        assert(n);
 +
 +        if (n->timer_event_source) {
 +                r = sd_event_source_set_time(n->timer_event_source, usec);
 +                if (r < 0)
 +                        return r;
 +
 +                return sd_event_source_set_enabled(n->timer_event_source, SD_EVENT_ONESHOT);
 +        }
 +
 +        if (usec == USEC_INFINITY)
 +                return 0;
 +
 +        r = sd_event_add_time(
 +                        UNIT(n)->manager->event,
 +                        &n->timer_event_source,
 +                        CLOCK_MONOTONIC,
 +                        usec, 0,
 +                        busname_dispatch_timer, n);
 +        if (r < 0)
 +                return r;
 +
 +        (void) sd_event_source_set_description(n->timer_event_source, "busname-timer");
 +
 +        return 0;
 +}
 +
 +static int busname_add_default_default_dependencies(BusName *n) {
 +        int r;
 +
 +        assert(n);
 +
-                 r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
++        r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
 +        if (r < 0)
 +                return r;
 +
 +        if (MANAGER_IS_SYSTEM(UNIT(n)->manager)) {
-         return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
++                r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
 +                if (r < 0)
 +                        return r;
 +        }
 +
-                 r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
++        return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
 +}
 +
 +static int busname_add_extras(BusName *n) {
 +        Unit *u = UNIT(n);
 +        int r;
 +
 +        assert(n);
 +
 +        if (!n->name) {
 +                r = unit_name_to_prefix(u->id, &n->name);
 +                if (r < 0)
 +                        return r;
 +        }
 +
 +        if (!u->description) {
 +                r = unit_set_description(u, n->name);
 +                if (r < 0)
 +                        return r;
 +        }
 +
 +        if (n->activating) {
 +                if (!UNIT_DEREF(n->service)) {
 +                        Unit *x;
 +
 +                        r = unit_load_related_unit(u, ".service", &x);
 +                        if (r < 0)
 +                                return r;
 +
 +                        unit_ref_set(&n->service, x);
 +                }
 +
-         SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
++                r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true, UNIT_DEPENDENCY_IMPLICIT);
 +                if (r < 0)
 +                        return r;
 +        }
 +
 +        if (u->default_dependencies) {
 +                r = busname_add_default_default_dependencies(n);
 +                if (r < 0)
 +                        return r;
 +        }
 +
 +        return 0;
 +}
 +
 +static int busname_verify(BusName *n) {
 +        char *e;
 +
 +        assert(n);
 +
 +        if (UNIT(n)->load_state != UNIT_LOADED)
 +                return 0;
 +
 +        if (!service_name_is_valid(n->name)) {
 +                log_unit_error(UNIT(n), "Name= setting is not a valid service name Refusing.");
 +                return -EINVAL;
 +        }
 +
 +        e = strjoina(n->name, ".busname");
 +        if (!unit_has_name(UNIT(n), e)) {
 +                log_unit_error(UNIT(n), "Name= setting doesn't match unit name. Refusing.");
 +                return -EINVAL;
 +        }
 +
 +        return 0;
 +}
 +
 +static int busname_load(Unit *u) {
 +        BusName *n = BUSNAME(u);
 +        int r;
 +
 +        assert(u);
 +        assert(u->load_state == UNIT_STUB);
 +
 +        r = unit_load_fragment_and_dropin(u);
 +        if (r < 0)
 +                return r;
 +
 +        if (u->load_state == UNIT_LOADED) {
 +                /* This is a new unit? Then let's add in some extras */
 +                r = busname_add_extras(n);
 +                if (r < 0)
 +                        return r;
 +        }
 +
 +        return busname_verify(n);
 +}
 +
 +static void busname_dump(Unit *u, FILE *f, const char *prefix) {
 +        BusName *n = BUSNAME(u);
 +
 +        assert(n);
 +        assert(f);
 +
 +        fprintf(f,
 +                "%sBus Name State: %s\n"
 +                "%sResult: %s\n"
 +                "%sName: %s\n"
 +                "%sActivating: %s\n"
 +                "%sAccept FD: %s\n",
 +                prefix, busname_state_to_string(n->state),
 +                prefix, busname_result_to_string(n->result),
 +                prefix, n->name,
 +                prefix, yes_no(n->activating),
 +                prefix, yes_no(n->accept_fd));
 +
 +        if (n->control_pid > 0)
 +                fprintf(f,
 +                        "%sControl PID: "PID_FMT"\n",
 +                        prefix, n->control_pid);
 +}
 +
 +static void busname_unwatch_fd(BusName *n) {
 +        int r;
 +
 +        assert(n);
 +
 +        if (!n->starter_event_source)
 +                return;
 +
 +        r = sd_event_source_set_enabled(n->starter_event_source, SD_EVENT_OFF);
 +        if (r < 0)
 +                log_unit_debug_errno(UNIT(n), r, "Failed to disable event source: %m");
 +}
 +
 +static int busname_watch_fd(BusName *n) {
 +        int r;
 +
 +        assert(n);
 +
 +        if (n->starter_fd < 0)
 +                return 0;
 +
 +        if (n->starter_event_source) {
 +                r = sd_event_source_set_enabled(n->starter_event_source, SD_EVENT_ON);
 +                if (r < 0)
 +                        goto fail;
 +        } else {
 +                r = sd_event_add_io(UNIT(n)->manager->event, &n->starter_event_source, n->starter_fd, EPOLLIN, busname_dispatch_io, n);
 +                if (r < 0)
 +                        goto fail;
 +
 +                (void) sd_event_source_set_description(n->starter_event_source, "busname-starter");
 +        }
 +
 +        return 0;
 +
 +fail:
 +        log_unit_warning_errno(UNIT(n), r, "Failed to watch starter fd: %m");
 +        busname_unwatch_fd(n);
 +        return r;
 +}
 +
 +static int busname_open_fd(BusName *n) {
 +        _cleanup_free_ char *path = NULL;
 +        const char *mode;
 +
 +        assert(n);
 +
 +        if (n->starter_fd >= 0)
 +                return 0;
 +
 +        mode = MANAGER_IS_SYSTEM(UNIT(n)->manager) ? "system" : "user";
 +        n->starter_fd = bus_kernel_open_bus_fd(mode, &path);
 +        if (n->starter_fd < 0)
 +                return log_unit_warning_errno(UNIT(n), n->starter_fd, "Failed to open %s: %m", path ?: "kdbus");
 +
 +        return 0;
 +}
 +
 +static void busname_set_state(BusName *n, BusNameState state) {
 +        BusNameState old_state;
 +        assert(n);
 +
 +        old_state = n->state;
 +        n->state = state;
 +
 +        if (!IN_SET(state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) {
 +                n->timer_event_source = sd_event_source_unref(n->timer_event_source);
 +                busname_unwatch_control_pid(n);
 +        }
 +
 +        if (state != BUSNAME_LISTENING)
 +                busname_unwatch_fd(n);
 +
 +        if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_MAKING, BUSNAME_REGISTERED, BUSNAME_RUNNING))
 +                busname_close_fd(n);
 +
 +        if (state != old_state)
 +                log_unit_debug(UNIT(n), "Changed %s -> %s", busname_state_to_string(old_state), busname_state_to_string(state));
 +
 +        unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
 +}
 +
 +static int busname_coldplug(Unit *u) {
 +        BusName *n = BUSNAME(u);
 +        int r;
 +
 +        assert(n);
 +        assert(n->state == BUSNAME_DEAD);
 +
 +        if (n->deserialized_state == n->state)
 +                return 0;
 +
 +        if (n->control_pid > 0 &&
 +            pid_is_unwaited(n->control_pid) &&
 +            IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) {
 +
 +                r = unit_watch_pid(UNIT(n), n->control_pid);
 +                if (r < 0)
 +                        return r;
 +
 +                r = busname_arm_timer(n, usec_add(u->state_change_timestamp.monotonic, n->timeout_usec));
 +                if (r < 0)
 +                        return r;
 +        }
 +
 +        if (IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_LISTENING, BUSNAME_REGISTERED, BUSNAME_RUNNING)) {
 +                r = busname_open_fd(n);
 +                if (r < 0)
 +                        return r;
 +        }
 +
 +        if (n->deserialized_state == BUSNAME_LISTENING) {
 +                r = busname_watch_fd(n);
 +                if (r < 0)
 +                        return r;
 +        }
 +
 +        busname_set_state(n, n->deserialized_state);
 +        return 0;
 +}
 +
 +static int busname_make_starter(BusName *n, pid_t *_pid) {
 +        pid_t pid;
 +        int r;
 +
 +        r = busname_arm_timer(n, usec_add(now(CLOCK_MONOTONIC), n->timeout_usec));
 +        if (r < 0)
 +                goto fail;
 +
 +        /* We have to resolve the user/group names out-of-process,
 +         * hence let's fork here. It's messy, but well, what can we
 +         * do? */
 +
 +        pid = fork();
 +        if (pid < 0)
 +                return -errno;
 +
 +        if (pid == 0) {
 +                int ret;
 +
 +                (void) default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1);
 +                (void) ignore_signals(SIGPIPE, -1);
 +                log_forget_fds();
 +
 +                r = bus_kernel_make_starter(n->starter_fd, n->name, n->activating, n->accept_fd, n->policy, n->policy_world);
 +                if (r < 0) {
 +                        ret = EXIT_MAKE_STARTER;
 +                        goto fail_child;
 +                }
 +
 +                _exit(0);
 +
 +        fail_child:
 +                log_open();
 +                log_error_errno(r, "Failed to create starter connection at step %s: %m", exit_status_to_string(ret, EXIT_STATUS_SYSTEMD));
 +
 +                _exit(ret);
 +        }
 +
 +        r = unit_watch_pid(UNIT(n), pid);
 +        if (r < 0)
 +                goto fail;
 +
 +        *_pid = pid;
 +        return 0;
 +
 +fail:
 +        n->timer_event_source = sd_event_source_unref(n->timer_event_source);
 +        return r;
 +}
 +
 +static void busname_enter_dead(BusName *n, BusNameResult f) {
 +        assert(n);
 +
 +        if (n->result == BUSNAME_SUCCESS)
 +                n->result = f;
 +
 +        busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
 +}
 +
 +static void busname_enter_signal(BusName *n, BusNameState state, BusNameResult f) {
 +        KillContext kill_context = {};
 +        int r;
 +
 +        assert(n);
 +
 +        if (n->result == BUSNAME_SUCCESS)
 +                n->result = f;
 +
 +        kill_context_init(&kill_context);
 +
 +        r = unit_kill_context(UNIT(n),
 +                              &kill_context,
 +                              state != BUSNAME_SIGTERM ? KILL_KILL : KILL_TERMINATE,
 +                              -1,
 +                              n->control_pid,
 +                              false);
 +        if (r < 0) {
 +                log_unit_warning_errno(UNIT(n), r, "Failed to kill control process: %m");
 +                goto fail;
 +        }
 +
 +        if (r > 0) {
 +                r = busname_arm_timer(n, usec_add(now(CLOCK_MONOTONIC), n->timeout_usec));
 +                if (r < 0) {
 +                        log_unit_warning_errno(UNIT(n), r, "Failed to arm timer: %m");
 +                        goto fail;
 +                }
 +
 +                busname_set_state(n, state);
 +        } else if (state == BUSNAME_SIGTERM)
 +                busname_enter_signal(n, BUSNAME_SIGKILL, BUSNAME_SUCCESS);
 +        else
 +                busname_enter_dead(n, BUSNAME_SUCCESS);
 +
 +        return;
 +
 +fail:
 +        busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
 +}
 +
 +static void busname_enter_listening(BusName *n) {
 +        int r;
 +
 +        assert(n);
 +
 +        if (n->activating) {
 +                r = busname_watch_fd(n);
 +                if (r < 0) {
 +                        log_unit_warning_errno(UNIT(n), r, "Failed to watch names: %m");
 +                        goto fail;
 +                }
 +
 +                busname_set_state(n, BUSNAME_LISTENING);
 +        } else
 +                busname_set_state(n, BUSNAME_REGISTERED);
 +
 +        return;
 +
 +fail:
 +        busname_enter_signal(n, BUSNAME_SIGTERM, BUSNAME_FAILURE_RESOURCES);
 +}
 +
 +static void busname_enter_making(BusName *n) {
 +        int r;
 +
 +        assert(n);
 +
 +        r = busname_open_fd(n);
 +        if (r < 0)
 +                goto fail;
 +
 +        if (n->policy) {
 +                /* If there is a policy, we need to resolve user/group
 +                 * names, which we can't do from PID1, hence let's
 +                 * fork. */
 +                busname_unwatch_control_pid(n);
 +
 +                r = busname_make_starter(n, &n->control_pid);
 +                if (r < 0) {
 +                        log_unit_warning_errno(UNIT(n), r, "Failed to fork 'making' task: %m");
 +                        goto fail;
 +                }
 +
 +                busname_set_state(n, BUSNAME_MAKING);
 +        } else {
 +                /* If there is no policy, we can do everything
 +                 * directly from PID 1, hence do so. */
 +
 +                r = bus_kernel_make_starter(n->starter_fd, n->name, n->activating, n->accept_fd, NULL, n->policy_world);
 +                if (r < 0) {
 +                        log_unit_warning_errno(UNIT(n), r, "Failed to make starter: %m");
 +                        goto fail;
 +                }
 +
 +                busname_enter_listening(n);
 +        }
 +
 +        return;
 +
 +fail:
 +        busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
 +}
 +
 +static void busname_enter_running(BusName *n) {
 +        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 +        bool pending = false;
 +        Unit *other;
 +        Iterator i;
 +        int r;
++        void *v;
 +
 +        assert(n);
 +
 +        if (!n->activating)
 +                return;
 +
 +        /* We don't take connections anymore if we are supposed to
 +         * shut down anyway */
 +
 +        if (unit_stop_pending(UNIT(n))) {
 +                log_unit_debug(UNIT(n), "Suppressing activation request since unit stop is scheduled.");
 +
 +                /* Flush all queued activation reqeuest by closing and reopening the connection */
 +                bus_kernel_drop_one(n->starter_fd);
 +
 +                busname_enter_listening(n);
 +                return;
 +        }
 +
 +        /* If there's already a start pending don't bother to do
 +         * anything */
++        HASHMAP_FOREACH_KEY(v, other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
 +                if (unit_active_or_pending(other)) {
 +                        pending = true;
 +                        break;
 +                }
 +
 +        if (!pending) {
 +                if (!UNIT_ISSET(n->service)) {
 +                        log_unit_error(UNIT(n), "Service to activate vanished, refusing activation.");
 +                        r = -ENOENT;
 +                        goto fail;
 +                }
 +
 +                r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, &error, NULL);
 +                if (r < 0)
 +                        goto fail;
 +        }
 +
 +        busname_set_state(n, BUSNAME_RUNNING);
 +        return;
 +
 +fail:
 +        log_unit_warning(UNIT(n), "Failed to queue service startup job: %s", bus_error_message(&error, r));
 +        busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
 +}
 +
 +static int busname_start(Unit *u) {
 +        BusName *n = BUSNAME(u);
 +        int r;
 +
 +        assert(n);
 +
 +        /* We cannot fulfill this request right now, try again later
 +         * please! */
 +        if (IN_SET(n->state, BUSNAME_SIGTERM, BUSNAME_SIGKILL))
 +                return -EAGAIN;
 +
 +        /* Already on it! */
 +        if (n->state == BUSNAME_MAKING)
 +                return 0;
 +
 +        if (n->activating && UNIT_ISSET(n->service)) {
 +                Service *service;
 +
 +                service = SERVICE(UNIT_DEREF(n->service));
 +
 +                if (UNIT(service)->load_state != UNIT_LOADED) {
 +                        log_unit_error(u, "Bus service %s not loaded, refusing.", UNIT(service)->id);
 +                        return -ENOENT;
 +                }
 +        }
 +
 +        assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
 +
 +        r = unit_start_limit_test(u);
 +        if (r < 0) {
 +                busname_enter_dead(n, BUSNAME_FAILURE_START_LIMIT_HIT);
 +                return r;
 +        }
 +
 +        r = unit_acquire_invocation_id(u);
 +        if (r < 0)
 +                return r;
 +
 +        n->result = BUSNAME_SUCCESS;
 +        busname_enter_making(n);
 +
 +        return 1;
 +}
 +
 +static int busname_stop(Unit *u) {
 +        BusName *n = BUSNAME(u);
 +
 +        assert(n);
 +
 +        /* Already on it */
 +        if (IN_SET(n->state, BUSNAME_SIGTERM, BUSNAME_SIGKILL))
 +                return 0;
 +
 +        /* If there's already something running, we go directly into
 +         * kill mode. */
 +
 +        if (n->state == BUSNAME_MAKING) {
 +                busname_enter_signal(n, BUSNAME_SIGTERM, BUSNAME_SUCCESS);
 +                return -EAGAIN;
 +        }
 +
 +        assert(IN_SET(n->state, BUSNAME_REGISTERED, BUSNAME_LISTENING, BUSNAME_RUNNING));
 +
 +        busname_enter_dead(n, BUSNAME_SUCCESS);
 +        return 1;
 +}
 +
 +static int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
 +        BusName *n = BUSNAME(u);
 +        int r;
 +
 +        assert(n);
 +        assert(f);
 +        assert(fds);
 +
 +        unit_serialize_item(u, f, "state", busname_state_to_string(n->state));
 +        unit_serialize_item(u, f, "result", busname_result_to_string(n->result));
 +
 +        if (n->control_pid > 0)
 +                unit_serialize_item_format(u, f, "control-pid", PID_FMT, n->control_pid);
 +
 +        r = unit_serialize_item_fd(u, f, fds, "starter-fd", n->starter_fd);
 +        if (r < 0)
 +                return r;
 +
 +        return 0;
 +}
 +
 +static int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
 +        BusName *n = BUSNAME(u);
 +
 +        assert(n);
 +        assert(key);
 +        assert(value);
 +
 +        if (streq(key, "state")) {
 +                BusNameState state;
 +
 +                state = busname_state_from_string(value);
 +                if (state < 0)
 +                        log_unit_debug(u, "Failed to parse state value: %s", value);
 +                else
 +                        n->deserialized_state = state;
 +
 +        } else if (streq(key, "result")) {
 +                BusNameResult f;
 +
 +                f = busname_result_from_string(value);
 +                if (f < 0)
 +                        log_unit_debug(u, "Failed to parse result value: %s", value);
 +                else if (f != BUSNAME_SUCCESS)
 +                        n->result = f;
 +
 +        } else if (streq(key, "control-pid")) {
 +                pid_t pid;
 +
 +                if (parse_pid(value, &pid) < 0)
 +                        log_unit_debug(u, "Failed to parse control-pid value: %s", value);
 +                else
 +                        n->control_pid = pid;
 +        } else if (streq(key, "starter-fd")) {
 +                int fd;
 +
 +                if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
 +                        log_unit_debug(u, "Failed to parse starter fd value: %s", value);
 +                else {
 +                        safe_close(n->starter_fd);
 +                        n->starter_fd = fdset_remove(fds, fd);
 +                }
 +        } else
 +                log_unit_debug(u, "Unknown serialization key: %s", key);
 +
 +        return 0;
 +}
 +
 +_pure_ static UnitActiveState busname_active_state(Unit *u) {
 +        assert(u);
 +
 +        return state_translation_table[BUSNAME(u)->state];
 +}
 +
 +_pure_ static const char *busname_sub_state_to_string(Unit *u) {
 +        assert(u);
 +
 +        return busname_state_to_string(BUSNAME(u)->state);
 +}
 +
 +static int busname_peek_message(BusName *n) {
 +        struct kdbus_cmd_recv cmd_recv = {
 +                .size = sizeof(cmd_recv),
 +                .flags = KDBUS_RECV_PEEK,
 +        };
 +        struct kdbus_cmd_free cmd_free = {
 +                .size = sizeof(cmd_free),
 +        };
 +        const char *comm = NULL;
 +        struct kdbus_item *d;
 +        struct kdbus_msg *k;
 +        size_t start, ps, sz, delta;
 +        void *p = MAP_FAILED;
 +        pid_t pid = 0;
 +        int r;
 +
 +        /* Generate a friendly debug log message about which process
 +         * caused triggering of this bus name. This simply peeks the
 +         * metadata of the first queued message and logs it. */
 +
 +        assert(n);
 +
 +        /* Let's shortcut things a bit, if debug logging is turned off
 +         * anyway. */
 +
 +        if (log_get_max_level() < LOG_DEBUG)
 +                return 0;
 +
 +        r = ioctl(n->starter_fd, KDBUS_CMD_RECV, &cmd_recv);
 +        if (r < 0) {
 +                if (errno == EINTR || errno == EAGAIN)
 +                        return 0;
 +
 +                return log_unit_error_errno(UNIT(n), errno, "Failed to query activation message: %m");
 +        }
 +
 +        /* We map as late as possible, and unmap imemdiately after
 +         * use. On 32bit address space is scarce and we want to be
 +         * able to handle a lot of activator connections at the same
 +         * time, and hence shouldn't keep the mmap()s around for
 +         * longer than necessary. */
 +
 +        ps = page_size();
 +        start = (cmd_recv.msg.offset / ps) * ps;
 +        delta = cmd_recv.msg.offset - start;
 +        sz = PAGE_ALIGN(delta + cmd_recv.msg.msg_size);
 +
 +        p = mmap(NULL, sz, PROT_READ, MAP_SHARED, n->starter_fd, start);
 +        if (p == MAP_FAILED) {
 +                r = log_unit_error_errno(UNIT(n), errno, "Failed to map activation message: %m");
 +                goto finish;
 +        }
 +
 +        k = (struct kdbus_msg *) ((uint8_t *) p + delta);
 +        KDBUS_ITEM_FOREACH(d, k, items) {
 +                switch (d->type) {
 +
 +                case KDBUS_ITEM_PIDS:
 +                        pid = d->pids.pid;
 +                        break;
 +
 +                case KDBUS_ITEM_PID_COMM:
 +                        comm = d->str;
 +                        break;
 +                }
 +        }
 +
 +        if (pid > 0)
 +                log_unit_debug(UNIT(n), "Activation triggered by process " PID_FMT " (%s)", pid, strna(comm));
 +
 +        r = 0;
 +
 +finish:
 +        if (p != MAP_FAILED)
 +                (void) munmap(p, sz);
 +
 +        cmd_free.offset = cmd_recv.msg.offset;
 +        if (ioctl(n->starter_fd, KDBUS_CMD_FREE, &cmd_free) < 0)
 +                log_unit_warning(UNIT(n), "Failed to free peeked message, ignoring: %m");
 +
 +        return r;
 +}
 +
 +static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
 +        BusName *n = userdata;
 +
 +        assert(n);
 +        assert(fd >= 0);
 +
 +        if (n->state != BUSNAME_LISTENING)
 +                return 0;
 +
 +        log_unit_debug(UNIT(n), "Activation request");
 +
 +        if (revents != EPOLLIN) {
 +                log_unit_error(UNIT(n), "Got unexpected poll event (0x%x) on starter fd.", revents);
 +                goto fail;
 +        }
 +
 +        busname_peek_message(n);
 +        busname_enter_running(n);
 +        return 0;
 +fail:
 +
 +        busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
 +        return 0;
 +}
 +
 +static void busname_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 +        BusName *n = BUSNAME(u);
 +        BusNameResult f;
 +
 +        assert(n);
 +        assert(pid >= 0);
 +
 +        if (pid != n->control_pid)
 +                return;
 +
 +        n->control_pid = 0;
 +
 +        if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
 +                f = BUSNAME_SUCCESS;
 +        else if (code == CLD_EXITED)
 +                f = BUSNAME_FAILURE_EXIT_CODE;
 +        else if (code == CLD_KILLED)
 +                f = BUSNAME_FAILURE_SIGNAL;
 +        else if (code == CLD_DUMPED)
 +                f = BUSNAME_FAILURE_CORE_DUMP;
 +        else
 +                assert_not_reached("Unknown sigchld code");
 +
 +        log_unit_full(u, f == BUSNAME_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0,
 +                      "Control process exited, code=%s status=%i", sigchld_code_to_string(code), status);
 +
 +        if (n->result == BUSNAME_SUCCESS)
 +                n->result = f;
 +
 +        switch (n->state) {
 +
 +        case BUSNAME_MAKING:
 +                if (f == BUSNAME_SUCCESS)
 +                        busname_enter_listening(n);
 +                else
 +                        busname_enter_signal(n, BUSNAME_SIGTERM, f);
 +                break;
 +
 +        case BUSNAME_SIGTERM:
 +        case BUSNAME_SIGKILL:
 +                busname_enter_dead(n, f);
 +                break;
 +
 +        default:
 +                assert_not_reached("Uh, control process died at wrong time.");
 +        }
 +
 +        /* Notify clients about changed exit status */
 +        unit_add_to_dbus_queue(u);
 +}
 +
 +static int busname_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
 +        BusName *n = BUSNAME(userdata);
 +
 +        assert(n);
 +        assert(n->timer_event_source == source);
 +
 +        switch (n->state) {
 +
 +        case BUSNAME_MAKING:
 +                log_unit_warning(UNIT(n), "Making timed out. Terminating.");
 +                busname_enter_signal(n, BUSNAME_SIGTERM, BUSNAME_FAILURE_TIMEOUT);
 +                break;
 +
 +        case BUSNAME_SIGTERM:
 +                log_unit_warning(UNIT(n), "Stopping timed out. Killing.");
 +                busname_enter_signal(n, BUSNAME_SIGKILL, BUSNAME_FAILURE_TIMEOUT);
 +                break;
 +
 +        case BUSNAME_SIGKILL:
 +                log_unit_warning(UNIT(n), "Processes still around after SIGKILL. Ignoring.");
 +                busname_enter_dead(n, BUSNAME_FAILURE_TIMEOUT);
 +                break;
 +
 +        default:
 +                assert_not_reached("Timeout at wrong time.");
 +        }
 +
 +        return 0;
 +}
 +
 +static void busname_reset_failed(Unit *u) {
 +        BusName *n = BUSNAME(u);
 +
 +        assert(n);
 +
 +        if (n->state == BUSNAME_FAILED)
 +                busname_set_state(n, BUSNAME_DEAD);
 +
 +        n->result = BUSNAME_SUCCESS;
 +}
 +
 +static void busname_trigger_notify(Unit *u, Unit *other) {
 +        BusName *n = BUSNAME(u);
 +
 +        assert(n);
 +        assert(other);
 +
 +        if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
 +                return;
 +
 +        if (other->start_limit_hit) {
 +                busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT);
 +                return;
 +        }
 +
 +        if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
 +                return;
 +
 +        if (IN_SET(SERVICE(other)->state,
 +                   SERVICE_DEAD, SERVICE_FAILED,
 +                   SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
 +                   SERVICE_AUTO_RESTART))
 +                busname_enter_listening(n);
 +
 +        if (SERVICE(other)->state == SERVICE_RUNNING)
 +                busname_set_state(n, BUSNAME_RUNNING);
 +}
 +
 +static int busname_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
 +        return unit_kill_common(u, who, signo, -1, BUSNAME(u)->control_pid, error);
 +}
 +
 +static int busname_get_timeout(Unit *u, usec_t *timeout) {
 +        BusName *n = BUSNAME(u);
 +        usec_t t;
 +        int r;
 +
 +        if (!n->timer_event_source)
 +                return 0;
 +
 +        r = sd_event_source_get_time(n->timer_event_source, &t);
 +        if (r < 0)
 +                return r;
 +        if (t == USEC_INFINITY)
 +                return 0;
 +
 +        *timeout = t;
 +        return 1;
 +}
 +
 +static bool busname_supported(void) {
 +        return is_kdbus_available();
 +}
 +
 +static int busname_control_pid(Unit *u) {
 +        BusName *n = BUSNAME(u);
 +
 +        assert(n);
 +
 +        return n->control_pid;
 +}
 +
 +static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
 +        [BUSNAME_SUCCESS] = "success",
 +        [BUSNAME_FAILURE_RESOURCES] = "resources",
 +        [BUSNAME_FAILURE_TIMEOUT] = "timeout",
 +        [BUSNAME_FAILURE_EXIT_CODE] = "exit-code",
 +        [BUSNAME_FAILURE_SIGNAL] = "signal",
 +        [BUSNAME_FAILURE_CORE_DUMP] = "core-dump",
 +        [BUSNAME_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
 +        [BUSNAME_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit",
 +};
 +
 +DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
 +
 +const UnitVTable busname_vtable = {
 +        .object_size = sizeof(BusName),
 +
 +        .sections =
 +                "Unit\0"
 +                "BusName\0"
 +                "Install\0",
 +        .private_section = "BusName",
 +
 +        .init = busname_init,
 +        .done = busname_done,
 +        .load = busname_load,
 +
 +        .coldplug = busname_coldplug,
 +
 +        .dump = busname_dump,
 +
 +        .start = busname_start,
 +        .stop = busname_stop,
 +
 +        .kill = busname_kill,
 +
 +        .get_timeout = busname_get_timeout,
 +
 +        .serialize = busname_serialize,
 +        .deserialize_item = busname_deserialize_item,
 +
 +        .active_state = busname_active_state,
 +        .sub_state_to_string = busname_sub_state_to_string,
 +
 +        .sigchld_event = busname_sigchld_event,
 +
 +        .trigger_notify = busname_trigger_notify,
 +
 +        .reset_failed = busname_reset_failed,
 +
 +        .supported = busname_supported,
 +
 +        .control_pid = busname_control_pid,
 +
 +        .bus_vtable = bus_busname_vtable,
 +
 +        .status_message_formats = {
 +                .finished_start_job = {
 +                        [JOB_DONE]       = "Listening on %s.",
 +                        [JOB_FAILED]     = "Failed to listen on %s.",
 +                },
 +                .finished_stop_job = {
 +                        [JOB_DONE]       = "Closed %s.",
 +                        [JOB_FAILED]     = "Failed stopping %s.",
 +                },
 +        },
 +};
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc src/core/dbus.c
Simple merge
Simple merge
@@@ -4069,14 -4102,26 +4150,34 @@@ void exec_context_dump(ExecContext *c, 
                          fprintf(f, "%sSyslogLevel: %s\n", prefix, lvl_str);
          }
  
 +        if (c->capabilities) {
 +                _cleanup_cap_free_charp_ char *t;
 +
 +                t = cap_to_text(c->capabilities, NULL);
 +                if (t)
 +                        fprintf(f, "%sCapabilities: %s\n", prefix, t);
 +        }
 +
+         if (c->log_level_max >= 0) {
+                 _cleanup_free_ char *t = NULL;
+                 (void) log_level_to_string_alloc(c->log_level_max, &t);
+                 fprintf(f, "%sLogLevelMax: %s\n", prefix, strna(t));
+         }
+         if (c->n_log_extra_fields > 0) {
+                 size_t j;
+                 for (j = 0; j < c->n_log_extra_fields; j++) {
+                         fprintf(f, "%sLogExtraFields: ", prefix);
+                         fwrite(c->log_extra_fields[j].iov_base,
+                                1, c->log_extra_fields[j].iov_len,
+                                f);
+                         fputc('\n', f);
+                 }
+         }
          if (c->secure_bits) {
                  _cleanup_free_ char *str = NULL;
  
Simple merge
Simple merge
@@@ -48,7 -54,9 +54,9 @@@ $1.SyslogIdentifier,             config
  $1.SyslogFacility,               config_parse_log_facility,          0,                             offsetof($1, exec_context.syslog_priority)
  $1.SyslogLevel,                  config_parse_log_level,             0,                             offsetof($1, exec_context.syslog_priority)
  $1.SyslogLevelPrefix,            config_parse_bool,                  0,                             offsetof($1, exec_context.syslog_level_prefix)
 -$1.Capabilities,                 config_parse_warn_compat,           DISABLED_LEGACY,               offsetof($1, exec_context)
+ $1.LogLevelMax,                  config_parse_log_level,             0,                             offsetof($1, exec_context.log_level_max)
+ $1.LogExtraFields,               config_parse_log_extra_fields,      0,                             offsetof($1, exec_context)
 +$1.Capabilities,                 config_parse_exec_capabilities,     0,                             offsetof($1, exec_context)
  $1.SecureBits,                   config_parse_exec_secure_bits,      0,                             offsetof($1, exec_context)
  $1.CapabilityBoundingSet,        config_parse_capability_set,        0,                             offsetof($1, exec_context.capability_bounding_set)
  $1.AmbientCapabilities,          config_parse_capability_set,        0,                             offsetof($1, exec_context.capability_ambient_set)
@@@ -370,19 -381,10 +381,19 @@@ EXEC_CONTEXT_CONFIG_ITEMS(Socket)m4_dn
  CGROUP_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl
  KILL_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl
  m4_dnl
 +BusName.Name,                    config_parse_string,                0,                             offsetof(BusName, name)
 +BusName.Activating,              config_parse_bool,                  0,                             offsetof(BusName, activating)
 +BusName.Service,                 config_parse_busname_service,       0,                             0
 +BusName.AllowUser,               config_parse_bus_policy,            0,                             0
 +BusName.AllowGroup,              config_parse_bus_policy,            0,                             0
 +BusName.AllowWorld,              config_parse_bus_policy_world,      0,                             offsetof(BusName, policy_world)
 +BusName.SELinuxContext,          config_parse_exec_selinux_context,  0,                             0
 +BusName.AcceptFileDescriptors,   config_parse_bool,                  0,                             offsetof(BusName, accept_fd)
 +m4_dnl
  Mount.What,                      config_parse_unit_string_printf,    0,                             offsetof(Mount, parameters_fragment.what)
- Mount.Where,                     config_parse_path,                  0,                             offsetof(Mount, where)
+ Mount.Where,                     config_parse_unit_path_printf,      0,                             offsetof(Mount, where)
  Mount.Options,                   config_parse_unit_string_printf,    0,                             offsetof(Mount, parameters_fragment.options)
- Mount.Type,                      config_parse_string,                0,                             offsetof(Mount, parameters_fragment.fstype)
+ Mount.Type,                      config_parse_unit_string_printf,    0,                             offsetof(Mount, parameters_fragment.fstype)
  Mount.TimeoutSec,                config_parse_sec_fix_0,             0,                             offsetof(Mount, timeout_usec)
  Mount.DirectoryMode,             config_parse_mode,                  0,                             offsetof(Mount, directory_mode)
  Mount.SloppyOptions,             config_parse_bool,                  0,                             offsetof(Mount, sloppy_options)
Simple merge
Simple merge
Simple merge
diff --cc src/core/main.c
@@@ -1387,283 -1444,839 +1444,833 @@@ static int fixup_environment(void) 
          return 0;
  }
  
- int main(int argc, char *argv[]) {
-         Manager *m = NULL;
-         int r, retval = EXIT_FAILURE;
-         usec_t before_startup, after_startup;
-         char timespan[FORMAT_TIMESPAN_MAX];
-         FDSet *fds = NULL;
-         bool reexecute = false;
-         const char *shutdown_verb = NULL;
-         dual_timestamp initrd_timestamp = DUAL_TIMESTAMP_NULL;
-         dual_timestamp userspace_timestamp = DUAL_TIMESTAMP_NULL;
-         dual_timestamp kernel_timestamp = DUAL_TIMESTAMP_NULL;
-         dual_timestamp security_start_timestamp = DUAL_TIMESTAMP_NULL;
-         dual_timestamp security_finish_timestamp = DUAL_TIMESTAMP_NULL;
-         static char systemd[] = "systemd";
-         bool skip_setup = false;
-         unsigned j;
-         bool loaded_policy = false;
-         bool arm_reboot_watchdog = false;
-         bool queue_default_job = false;
-         bool empty_etc = false;
-         char *switch_root_dir = NULL, *switch_root_init = NULL;
-         struct rlimit saved_rlimit_nofile = RLIMIT_MAKE_CONST(0), saved_rlimit_memlock = RLIMIT_MAKE_CONST((rlim_t) -1);
-         const char *error_message = NULL;
+ static void redirect_telinit(int argc, char *argv[]) {
+         /* This is compatibility support for SysV, where calling init as a user is identical to telinit. */
  
  #if HAVE_SYSV_COMPAT
-         if (getpid_cached() != 1 && strstr(program_invocation_short_name, "init")) {
-                 /* This is compatibility support for SysV, where
-                  * calling init as a user is identical to telinit. */
+         if (getpid_cached() == 1)
+                 return;
  
-                 execv(SYSTEMCTL_BINARY_PATH, argv);
-                 log_error_errno(errno, "Failed to exec " SYSTEMCTL_BINARY_PATH ": %m");
-                 return 1;
-         }
- #endif
+         if (!strstr(program_invocation_short_name, "init"))
+                 return;
  
-         dual_timestamp_from_monotonic(&kernel_timestamp, 0);
-         dual_timestamp_get(&userspace_timestamp);
+         execv(SYSTEMCTL_BINARY_PATH, argv);
+         log_error_errno(errno, "Failed to exec " SYSTEMCTL_BINARY_PATH ": %m");
+         exit(1);
+ #endif
+ }
  
-         /* Determine if this is a reexecution or normal bootup. We do
-          * the full command line parsing much later, so let's just
-          * have a quick peek here. */
-         if (strv_find(argv+1, "--deserialize"))
-                 skip_setup = true;
+ static int become_shutdown(
+                 const char *shutdown_verb,
+                 int retval) {
  
-         /* If we have switched root, do all the special setup
-          * things */
-         if (strv_find(argv+1, "--switched-root"))
-                 skip_setup = false;
+         char log_level[DECIMAL_STR_MAX(int) + 1],
+                 exit_code[DECIMAL_STR_MAX(uint8_t) + 1];
  
-         /* If we get started via the /sbin/init symlink then we are
-            called 'init'. After a subsequent reexecution we are then
-            called 'systemd'. That is confusing, hence let's call us
-            systemd right-away. */
-         program_invocation_short_name = systemd;
-         (void) prctl(PR_SET_NAME, systemd);
+         const char* command_line[11] = {
+                 SYSTEMD_SHUTDOWN_BINARY_PATH,
+                 shutdown_verb,
+                 "--log-level", log_level,
+                 "--log-target",
+         };
  
-         saved_argv = argv;
-         saved_argc = argc;
+         _cleanup_strv_free_ char **env_block = NULL;
+         size_t pos = 5;
+         int r;
  
-         log_set_upgrade_syslog_to_journal(true);
+         assert(shutdown_verb);
+         assert(!command_line[pos]);
+         env_block = strv_copy(environ);
  
-         if (getpid_cached() == 1) {
-                 /* Disable the umask logic */
-                 umask(0);
+         xsprintf(log_level, "%d", log_get_max_level());
  
-                 /* Always reopen /dev/console when running as PID 1 or one of its pre-execve() children. This is
-                  * important so that we never end up logging to any foreign stderr, for example if we have to log in a
-                  * child process right before execve()'ing the actual binary, at a point in time where socket
-                  * activation stderr/stdout area already set up. */
-                 log_set_always_reopen_console(true);
-         }
+         switch (log_get_target()) {
  
-         if (getpid_cached() == 1 && detect_container() <= 0) {
+         case LOG_TARGET_KMSG:
+         case LOG_TARGET_JOURNAL_OR_KMSG:
+         case LOG_TARGET_SYSLOG_OR_KMSG:
+                 command_line[pos++] = "kmsg";
+                 break;
  
-                 /* Running outside of a container as PID 1 */
-                 arg_system = true;
-                 log_set_target(LOG_TARGET_KMSG);
-                 log_open();
+         case LOG_TARGET_NULL:
+                 command_line[pos++] = "null";
+                 break;
  
-                 if (in_initrd())
-                         initrd_timestamp = userspace_timestamp;
+         case LOG_TARGET_CONSOLE:
+         default:
+                 command_line[pos++] = "console";
+                 break;
+         };
  
-                 if (!skip_setup) {
-                         r = mount_setup_early();
-                         if (r < 0) {
-                                 error_message = "Failed to mount early API filesystems";
-                                 goto finish;
-                         }
+         if (log_get_show_color())
+                 command_line[pos++] = "--log-color";
  
-                         dual_timestamp_get(&security_start_timestamp);
-                         if (mac_selinux_setup(&loaded_policy) < 0) {
-                                 error_message = "Failed to load SELinux policy";
-                                 goto finish;
-                         } else if (mac_smack_setup(&loaded_policy) < 0) {
-                                 error_message = "Failed to load SMACK policy";
-                                 goto finish;
-                         } else if (ima_setup() < 0) {
-                                 error_message = "Failed to load IMA policy";
-                                 goto finish;
-                         }
-                         dual_timestamp_get(&security_finish_timestamp);
-                 }
+         if (log_get_show_location())
+                 command_line[pos++] = "--log-location";
  
-                 if (mac_selinux_init() < 0) {
-                         error_message = "Failed to initialize SELinux policy";
-                         goto finish;
-                 }
+         if (streq(shutdown_verb, "exit")) {
+                 command_line[pos++] = "--exit-code";
+                 command_line[pos++] = exit_code;
+                 xsprintf(exit_code, "%d", retval);
+         }
  
-                 if (!skip_setup) {
-                         if (clock_is_localtime(NULL) > 0) {
-                                 int min;
-                                 /*
-                                  * The very first call of settimeofday() also does a time warp in the kernel.
-                                  *
-                                  * In the rtc-in-local time mode, we set the kernel's timezone, and rely on
-                                  * external tools to take care of maintaining the RTC and do all adjustments.
-                                  * This matches the behavior of Windows, which leaves the RTC alone if the
-                                  * registry tells that the RTC runs in UTC.
-                                  */
-                                 r = clock_set_timezone(&min);
-                                 if (r < 0)
-                                         log_error_errno(r, "Failed to apply local time delta, ignoring: %m");
-                                 else
-                                         log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min);
-                         } else if (!in_initrd()) {
-                                 /*
-                                  * Do a dummy very first call to seal the kernel's time warp magic.
-                                  *
-                                  * Do not call this from inside the initrd. The initrd might not
-                                  * carry /etc/adjtime with LOCAL, but the real system could be set up
-                                  * that way. In such case, we need to delay the time-warp or the sealing
-                                  * until we reach the real system.
-                                  *
-                                  * Do no set the kernel's timezone. The concept of local time cannot
-                                  * be supported reliably, the time will jump or be incorrect at every daylight
-                                  * saving time change. All kernel local time concepts will be treated
-                                  * as UTC that way.
-                                  */
-                                 clock_reset_timewarp();
-                         }
-                 }
+         assert(pos < ELEMENTSOF(command_line));
  
-                 /* Set the default for later on, but don't actually
-                  * open the logs like this for now. Note that if we
-                  * are transitioning from the initrd there might still
-                  * be journal fd open, and we shouldn't attempt
-                  * opening that before we parsed /proc/cmdline which
-                  * might redirect output elsewhere. */
-                 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
+         if (streq(shutdown_verb, "reboot") &&
+             arg_shutdown_watchdog > 0 &&
+             arg_shutdown_watchdog != USEC_INFINITY) {
  
-         } else if (getpid_cached() == 1) {
-                 /* Running inside a container, as PID 1 */
-                 arg_system = true;
-                 log_set_target(LOG_TARGET_CONSOLE);
-                 log_close_console(); /* force reopen of /dev/console */
-                 log_open();
+                 char *e;
  
-                 /* For later on, see above... */
-                 log_set_target(LOG_TARGET_JOURNAL);
+                 /* If we reboot let's set the shutdown
+                  * watchdog and tell the shutdown binary to
+                  * repeatedly ping it */
+                 r = watchdog_set_timeout(&arg_shutdown_watchdog);
+                 watchdog_close(r < 0);
  
-                 /* clear the kernel timestamp,
-                  * because we are in a container */
-                 kernel_timestamp = DUAL_TIMESTAMP_NULL;
-         } else {
-                 /* Running as user instance */
-                 arg_system = false;
-                 log_set_target(LOG_TARGET_AUTO);
-                 log_open();
+                 /* Tell the binary how often to ping, ignore failure */
+                 if (asprintf(&e, "WATCHDOG_USEC="USEC_FMT, arg_shutdown_watchdog) > 0)
+                         (void) strv_consume(&env_block, e);
  
-                 /* clear the kernel timestamp,
-                  * because we are not PID 1 */
-                 kernel_timestamp = DUAL_TIMESTAMP_NULL;
-         }
+                 if (arg_watchdog_device &&
+                     asprintf(&e, "WATCHDOG_DEVICE=%s", arg_watchdog_device) > 0)
+                         (void) strv_consume(&env_block, e);
+         } else
+                 watchdog_close(true);
  
-         if (getpid_cached() == 1) {
-                 /* Don't limit the core dump size, so that coredump handlers such as systemd-coredump (which honour the limit)
-                  * will process core dumps for system services by default. */
-                 if (setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
-                         log_warning_errno(errno, "Failed to set RLIMIT_CORE: %m");
+         /* Avoid the creation of new processes forked by the
+          * kernel; at this point, we will not listen to the
+          * signals anyway */
+         if (detect_container() <= 0)
+                 (void) cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER);
  
-                 /* But at the same time, turn off the core_pattern logic by default, so that no coredumps are stored
-                  * until the systemd-coredump tool is enabled via sysctl. */
-                 if (!skip_setup)
-                         (void) write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0);
-         }
+         execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block);
+         return -errno;
+ }
  
-         if (arg_system) {
-                 if (fixup_environment() < 0) {
-                         error_message = "Failed to fix up PID1 environment";
-                         goto finish;
-                 }
+ static void initialize_clock(void) {
+         int r;
  
-                 /* Try to figure out if we can use colors with the console. No
-                  * need to do that for user instances since they never log
-                  * into the console. */
-                 log_show_color(colors_enabled());
-                 r = make_null_stdio();
+         if (clock_is_localtime(NULL) > 0) {
+                 int min;
+                 /*
+                  * The very first call of settimeofday() also does a time warp in the kernel.
+                  *
+                  * In the rtc-in-local time mode, we set the kernel's timezone, and rely on external tools to take care
+                  * of maintaining the RTC and do all adjustments.  This matches the behavior of Windows, which leaves
+                  * the RTC alone if the registry tells that the RTC runs in UTC.
+                  */
+                 r = clock_set_timezone(&min);
                  if (r < 0)
-                         log_warning_errno(r, "Failed to redirect standard streams to /dev/null: %m");
+                         log_error_errno(r, "Failed to apply local time delta, ignoring: %m");
+                 else
+                         log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min);
+         } else if (!in_initrd()) {
+                 /*
+                  * Do a dummy very first call to seal the kernel's time warp magic.
+                  *
+                  * Do not call this from inside the initrd. The initrd might not carry /etc/adjtime with LOCAL, but the
+                  * real system could be set up that way. In such case, we need to delay the time-warp or the sealing
+                  * until we reach the real system.
+                  *
+                  * Do no set the kernel's timezone. The concept of local time cannot be supported reliably, the time
+                  * will jump or be incorrect at every daylight saving time change. All kernel local time concepts will
+                  * be treated as UTC that way.
+                  */
+                 (void) clock_reset_timewarp();
          }
 -
 -        r = clock_apply_epoch();
 -        if (r < 0)
 -                log_error_errno(r, "Current system time is before build time, but cannot correct: %m");
 -        else if (r > 0)
 -                log_info("System time before build time, advancing clock.");
+ }
  
-         r = initialize_join_controllers();
-         if (r < 0) {
-                 error_message = "Failed to initialize cgroup controllers";
-                 goto finish;
-         }
+ static void initialize_coredump(bool skip_setup) {
  
-         /* Mount /proc, /sys and friends, so that /proc/cmdline and
-          * /proc/$PID/fd is available. */
-         if (getpid_cached() == 1) {
+         if (getpid_cached() != 1)
+                 return;
  
-                 /* Load the kernel modules early, so that we kdbus.ko is loaded before kdbusfs shall be mounted */
-                 if (!skip_setup)
-                         kmod_setup();
+         /* Don't limit the core dump size, so that coredump handlers such as systemd-coredump (which honour the limit)
+          * will process core dumps for system services by default. */
+         if (setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
+                 log_warning_errno(errno, "Failed to set RLIMIT_CORE: %m");
  
-                 r = mount_setup(loaded_policy);
-                 if (r < 0) {
-                         error_message = "Failed to mount API filesystems";
-                         goto finish;
-                 }
-         }
+         /* But at the same time, turn off the core_pattern logic by default, so that no coredumps are stored
+          * until the systemd-coredump tool is enabled via sysctl. */
+         if (!skip_setup)
+                 (void) write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0);
+ }
  
-         /* Reset all signal handlers. */
-         (void) reset_all_signal_handlers();
-         (void) ignore_signals(SIGNALS_IGNORE, -1);
+ static void do_reexecute(
+                 int argc,
+                 char *argv[],
+                 const struct rlimit *saved_rlimit_nofile,
+                 const struct rlimit *saved_rlimit_memlock,
+                 FDSet *fds,
+                 const char *switch_root_dir,
+                 const char *switch_root_init,
+                 const char **ret_error_message) {
+         unsigned i, j, args_size;
+         const char **args;
+         int r;
  
-         arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U);
+         assert(saved_rlimit_nofile);
+         assert(saved_rlimit_memlock);
+         assert(ret_error_message);
  
-         if (parse_config_file() < 0) {
-                 error_message = "Failed to parse config file";
-                 goto finish;
-         }
+         /* Close and disarm the watchdog, so that the new instance can reinitialize it, but doesn't get rebooted while
+          * we do that */
+         watchdog_close(true);
  
-         if (arg_system) {
-                 r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0);
+         /* Reset the RLIMIT_NOFILE to the kernel default, so that the new systemd can pass the kernel default to its
+          * child processes */
+         if (saved_rlimit_nofile->rlim_cur > 0)
+                 (void) setrlimit(RLIMIT_NOFILE, saved_rlimit_nofile);
+         if (saved_rlimit_memlock->rlim_cur != (rlim_t) -1)
+                 (void) setrlimit(RLIMIT_MEMLOCK, saved_rlimit_memlock);
+         if (switch_root_dir) {
+                 /* Kill all remaining processes from the initrd, but don't wait for them, so that we can handle the
+                  * SIGCHLD for them after deserializing. */
+                 broadcast_signal(SIGTERM, false, true);
+                 /* And switch root with MS_MOVE, because we remove the old directory afterwards and detach it. */
+                 r = switch_root(switch_root_dir, "/mnt", true, MS_MOVE);
                  if (r < 0)
-                         log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
+                         log_error_errno(r, "Failed to switch root, trying to continue: %m");
          }
  
-         /* Note that this also parses bits from the kernel command
-          * line, including "debug". */
-         log_parse_environment();
+         args_size = MAX(6, argc+1);
+         args = newa(const char*, args_size);
  
-         if (parse_argv(argc, argv) < 0) {
-                 error_message = "Failed to parse commandline arguments";
-                 goto finish;
-         }
+         if (!switch_root_init) {
+                 char sfd[DECIMAL_STR_MAX(int) + 1];
  
-         /* Initialize default unit */
-         if (!arg_default_unit) {
-                 arg_default_unit = strdup(SPECIAL_DEFAULT_TARGET);
-                 if (!arg_default_unit) {
-                         r = log_oom();
-                         error_message = "Failed to set default unit";
-                         goto finish;
-                 }
-         }
+                 /* First try to spawn ourselves with the right path, and with full serialization. We do this only if
+                  * the user didn't specify an explicit init to spawn. */
  
-         if (arg_action == ACTION_TEST &&
-             geteuid() == 0) {
-                 log_error("Don't run test mode as root.");
-                 goto finish;
-         }
+                 assert(arg_serialization);
+                 assert(fds);
  
-         if (!arg_system &&
-             arg_action == ACTION_RUN &&
-             sd_booted() <= 0) {
-                 log_error("Trying to run as user instance, but the system has not been booted with systemd.");
-                 goto finish;
-         }
+                 xsprintf(sfd, "%i", fileno(arg_serialization));
  
-         if (arg_system &&
-             arg_action == ACTION_RUN &&
-             running_in_chroot() > 0) {
-                 log_error("Cannot be run in a chroot() environment.");
-                 goto finish;
+                 i = 0;
+                 args[i++] = SYSTEMD_BINARY_PATH;
+                 if (switch_root_dir)
+                         args[i++] = "--switched-root";
+                 args[i++] = arg_system ? "--system" : "--user";
+                 args[i++] = "--deserialize";
+                 args[i++] = sfd;
+                 args[i++] = NULL;
+                 assert(i <= args_size);
+                 /*
+                  * We want valgrind to print its memory usage summary before reexecution.  Valgrind won't do this is on
+                  * its own on exec(), but it will do it on exit().  Hence, to ensure we get a summary here, fork() off
+                  * a child, let it exit() cleanly, so that it prints the summary, and wait() for it in the parent,
+                  * before proceeding into the exec().
+                  */
+                 valgrind_summary_hack();
+                 (void) execv(args[0], (char* const*) args);
+                 log_debug_errno(errno, "Failed to execute our own binary, trying fallback: %m");
+         }
+         /* Try the fallback, if there is any, without any serialization. We pass the original argv[] and envp[]. (Well,
+          * modulo the ordering changes due to getopt() in argv[], and some cleanups in envp[], but let's hope that
+          * doesn't matter.) */
+         arg_serialization = safe_fclose(arg_serialization);
+         fds = fdset_free(fds);
+         /* Reopen the console */
+         (void) make_console_stdio();
+         for (j = 1, i = 1; j < (unsigned) argc; j++)
+                 args[i++] = argv[j];
+         args[i++] = NULL;
+         assert(i <= args_size);
+         /* Reenable any blocked signals, especially important if we switch from initial ramdisk to init=... */
+         (void) reset_all_signal_handlers();
+         (void) reset_signal_mask();
+         if (switch_root_init) {
+                 args[0] = switch_root_init;
+                 (void) execv(args[0], (char* const*) args);
+                 log_warning_errno(errno, "Failed to execute configured init, trying fallback: %m");
+         }
+         args[0] = "/sbin/init";
+         (void) execv(args[0], (char* const*) args);
+         r = -errno;
+         manager_status_printf(NULL, STATUS_TYPE_EMERGENCY,
+                               ANSI_HIGHLIGHT_RED "  !!  " ANSI_NORMAL,
+                               "Failed to execute /sbin/init");
+         if (r == -ENOENT) {
+                 log_warning("No /sbin/init, trying fallback");
+                 args[0] = "/bin/sh";
+                 args[1] = NULL;
+                 (void) execv(args[0], (char* const*) args);
+                 log_error_errno(errno, "Failed to execute /bin/sh, giving up: %m");
+         } else
+                 log_warning_errno(r, "Failed to execute /sbin/init, giving up: %m");
+         *ret_error_message = "Failed to execute fallback shell";
+ }
+ static int invoke_main_loop(
+                 Manager *m,
+                 bool *ret_reexecute,
+                 int *ret_retval,                   /* Return parameters relevant for shutting down */
+                 const char **ret_shutdown_verb,    /* â€¦ */
+                 FDSet **ret_fds,                   /* Return parameters for reexecuting */
+                 char **ret_switch_root_dir,        /* â€¦ */
+                 char **ret_switch_root_init,       /* â€¦ */
+                 const char **ret_error_message) {
+         int r;
+         assert(m);
+         assert(ret_reexecute);
+         assert(ret_retval);
+         assert(ret_shutdown_verb);
+         assert(ret_fds);
+         assert(ret_switch_root_dir);
+         assert(ret_switch_root_init);
+         assert(ret_error_message);
+         for (;;) {
+                 r = manager_loop(m);
+                 if (r < 0) {
+                         *ret_error_message = "Failed to run main loop";
+                         return log_emergency_errno(r, "Failed to run main loop: %m");
+                 }
+                 switch (m->exit_code) {
+                 case MANAGER_RELOAD:
+                         log_info("Reloading.");
+                         r = parse_config_file();
+                         if (r < 0)
+                                 log_warning_errno(r, "Failed to parse config file, ignoring: %m");
+                         set_manager_defaults(m);
+                         r = manager_reload(m);
+                         if (r < 0)
+                                 log_warning_errno(r, "Failed to reload, ignoring: %m");
+                         break;
+                 case MANAGER_REEXECUTE:
+                         r = prepare_reexecute(m, &arg_serialization, ret_fds, false);
+                         if (r < 0) {
+                                 *ret_error_message = "Failed to prepare for reexecution";
+                                 return r;
+                         }
+                         log_notice("Reexecuting.");
+                         *ret_reexecute = true;
+                         *ret_retval = EXIT_SUCCESS;
+                         *ret_shutdown_verb = NULL;
+                         *ret_switch_root_dir = *ret_switch_root_init = NULL;
+                         return 0;
+                 case MANAGER_SWITCH_ROOT:
+                         if (!m->switch_root_init) {
+                                 r = prepare_reexecute(m, &arg_serialization, ret_fds, true);
+                                 if (r < 0) {
+                                         *ret_error_message = "Failed to prepare for reexecution";
+                                         return r;
+                                 }
+                         } else
+                                 *ret_fds = NULL;
+                         log_notice("Switching root.");
+                         *ret_reexecute = true;
+                         *ret_retval = EXIT_SUCCESS;
+                         *ret_shutdown_verb = NULL;
+                         /* Steal the switch root parameters */
+                         *ret_switch_root_dir = m->switch_root;
+                         *ret_switch_root_init = m->switch_root_init;
+                         m->switch_root = m->switch_root_init = NULL;
+                         return 0;
+                 case MANAGER_EXIT:
+                         if (MANAGER_IS_USER(m)) {
+                                 log_debug("Exit.");
+                                 *ret_reexecute = false;
+                                 *ret_retval = m->return_value;
+                                 *ret_shutdown_verb = NULL;
+                                 *ret_fds = NULL;
+                                 *ret_switch_root_dir = *ret_switch_root_init = NULL;
+                                 return 0;
+                         }
+                         _fallthrough_;
+                 case MANAGER_REBOOT:
+                 case MANAGER_POWEROFF:
+                 case MANAGER_HALT:
+                 case MANAGER_KEXEC: {
+                         static const char * const table[_MANAGER_EXIT_CODE_MAX] = {
+                                 [MANAGER_EXIT] = "exit",
+                                 [MANAGER_REBOOT] = "reboot",
+                                 [MANAGER_POWEROFF] = "poweroff",
+                                 [MANAGER_HALT] = "halt",
+                                 [MANAGER_KEXEC] = "kexec"
+                         };
+                         log_notice("Shutting down.");
+                         *ret_reexecute = false;
+                         *ret_retval = m->return_value;
+                         assert_se(*ret_shutdown_verb = table[m->exit_code]);
+                         *ret_fds = NULL;
+                         *ret_switch_root_dir = *ret_switch_root_init = NULL;
+                         return 0;
+                 }
+                 default:
+                         assert_not_reached("Unknown exit code.");
+                 }
+         }
+ }
+ static void log_execution_mode(bool *ret_first_boot) {
+         assert(ret_first_boot);
+         if (arg_system) {
+                 int v;
+                 log_info(PACKAGE_STRING " running in %ssystem mode. (" SYSTEMD_FEATURES ")",
+                          arg_action == ACTION_TEST ? "test " : "" );
+                 v = detect_virtualization();
+                 if (v > 0)
+                         log_info("Detected virtualization %s.", virtualization_to_string(v));
+                 log_info("Detected architecture %s.", architecture_to_string(uname_architecture()));
+                 if (in_initrd()) {
+                         *ret_first_boot = false;
+                         log_info("Running in initial RAM disk.");
+                 } else {
+                         /* Let's check whether we are in first boot, i.e. whether /etc is still unpopulated. We use
+                          * /etc/machine-id as flag file, for this: if it exists we assume /etc is populated, if it
+                          * doesn't it's unpopulated. This allows container managers and installers to provision a
+                          * couple of files already. If the container manager wants to provision the machine ID itself
+                          * it should pass $container_uuid to PID 1. */
+                         *ret_first_boot = access("/etc/machine-id", F_OK) < 0;
+                         if (*ret_first_boot)
+                                 log_info("Running with unpopulated /etc.");
+                 }
+         } else {
+                 _cleanup_free_ char *t;
+                 t = uid_to_name(getuid());
+                 log_debug(PACKAGE_STRING " running in %suser mode for user " UID_FMT "/%s. (" SYSTEMD_FEATURES ")",
+                           arg_action == ACTION_TEST ? " test" : "", getuid(), strna(t));
+                 *ret_first_boot = false;
+         }
+ }
+ static int initialize_runtime(
+                 bool skip_setup,
+                 struct rlimit *saved_rlimit_nofile,
+                 struct rlimit *saved_rlimit_memlock,
+                 const char **ret_error_message) {
+         int r;
+         assert(ret_error_message);
+         /* Sets up various runtime parameters. Many of these initializations are conditionalized:
+          *
+          * - Some only apply to --system instances
+          * - Some only apply to --user instances
+          * - Some only apply when we first start up, but not when we reexecute
+          */
+         if (arg_system && !skip_setup) {
+                 if (arg_show_status > 0)
+                         status_welcome();
+                 hostname_setup();
+                 machine_id_setup(NULL, arg_machine_id, NULL);
+                 loopback_setup();
+                 bump_unix_max_dgram_qlen();
+                 test_usr();
+                 write_container_id();
+         }
+         if (arg_system && arg_watchdog_device) {
+                 r = watchdog_set_device(arg_watchdog_device);
+                 if (r < 0)
+                         log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m",
+                                           arg_watchdog_device);
+         }
+         if (arg_system && arg_runtime_watchdog > 0 && arg_runtime_watchdog != USEC_INFINITY)
+                 watchdog_set_timeout(&arg_runtime_watchdog);
+         if (arg_timer_slack_nsec != NSEC_INFINITY)
+                 if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0)
+                         log_error_errno(errno, "Failed to adjust timer slack: %m");
+         if (arg_system && !cap_test_all(arg_capability_bounding_set)) {
+                 r = capability_bounding_set_drop_usermode(arg_capability_bounding_set);
+                 if (r < 0) {
+                         *ret_error_message = "Failed to drop capability bounding set of usermode helpers";
+                         return log_emergency_errno(r, "Failed to drop capability bounding set of usermode helpers: %m");
+                 }
+                 r = capability_bounding_set_drop(arg_capability_bounding_set, true);
+                 if (r < 0) {
+                         *ret_error_message = "Failed to drop capability bounding set";
+                         return log_emergency_errno(r, "Failed to drop capability bounding set: %m");
+                 }
+         }
+         if (arg_syscall_archs) {
+                 r = enforce_syscall_archs(arg_syscall_archs);
+                 if (r < 0) {
+                         *ret_error_message = "Failed to set syscall architectures";
+                         return r;
+                 }
+         }
+         if (!arg_system)
+                 /* Become reaper of our children */
+                 if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0)
+                         log_warning_errno(errno, "Failed to make us a subreaper: %m");
+         if (arg_system) {
+                 /* Bump up RLIMIT_NOFILE for systemd itself */
+                 (void) bump_rlimit_nofile(saved_rlimit_nofile);
+                 (void) bump_rlimit_memlock(saved_rlimit_memlock);
+         }
+         return 0;
+ }
+ static int do_queue_default_job(
+                 Manager *m,
+                 const char **ret_error_message) {
+         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+         Job *default_unit_job;
+         Unit *target = NULL;
+         int r;
+         log_debug("Activating default unit: %s", arg_default_unit);
+         r = manager_load_unit(m, arg_default_unit, NULL, &error, &target);
+         if (r < 0)
+                 log_error("Failed to load default target: %s", bus_error_message(&error, r));
+         else if (IN_SET(target->load_state, UNIT_ERROR, UNIT_NOT_FOUND))
+                 log_error_errno(target->load_error, "Failed to load default target: %m");
+         else if (target->load_state == UNIT_MASKED)
+                 log_error("Default target masked.");
+         if (!target || target->load_state != UNIT_LOADED) {
+                 log_info("Trying to load rescue target...");
+                 r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
+                 if (r < 0) {
+                         *ret_error_message = "Failed to load rescue target";
+                         return log_emergency_errno(r, "Failed to load rescue target: %s", bus_error_message(&error, r));
+                 } else if (IN_SET(target->load_state, UNIT_ERROR, UNIT_NOT_FOUND)) {
+                         *ret_error_message = "Failed to load rescue target";
+                         return log_emergency_errno(target->load_error, "Failed to load rescue target: %m");
+                 } else if (target->load_state == UNIT_MASKED) {
+                         *ret_error_message = "Rescue target masked";
+                         log_emergency("Rescue target masked.");
+                         return -ERFKILL;
+                 }
+         }
+         assert(target->load_state == UNIT_LOADED);
+         r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, &error, &default_unit_job);
+         if (r == -EPERM) {
+                 log_debug_errno(r, "Default target could not be isolated, starting instead: %s", bus_error_message(&error, r));
+                 sd_bus_error_free(&error);
+                 r = manager_add_job(m, JOB_START, target, JOB_REPLACE, &error, &default_unit_job);
+                 if (r < 0) {
+                         *ret_error_message = "Failed to start default target";
+                         return log_emergency_errno(r, "Failed to start default target: %s", bus_error_message(&error, r));
+                 }
+         } else if (r < 0) {
+                 *ret_error_message = "Failed to isolate default target";
+                 return log_emergency_errno(r, "Failed to isolate default target: %s", bus_error_message(&error, r));
+         }
+         m->default_unit_job_id = default_unit_job->id;
+         return 0;
+ }
+ static void free_arguments(void) {
+         size_t j;
+         /* Frees all arg_* variables, with the exception of arg_serialization */
+         for (j = 0; j < ELEMENTSOF(arg_default_rlimit); j++)
+                 arg_default_rlimit[j] = mfree(arg_default_rlimit[j]);
+         arg_default_unit = mfree(arg_default_unit);
+         arg_confirm_spawn = mfree(arg_confirm_spawn);
+         arg_join_controllers = strv_free_free(arg_join_controllers);
+         arg_default_environment = strv_free(arg_default_environment);
+         arg_syscall_archs = set_free(arg_syscall_archs);
+ }
+ int main(int argc, char *argv[]) {
+         Manager *m = NULL;
+         int r, retval = EXIT_FAILURE;
+         usec_t before_startup, after_startup;
+         char timespan[FORMAT_TIMESPAN_MAX];
+         FDSet *fds = NULL;
+         bool reexecute = false;
+         const char *shutdown_verb = NULL;
+         dual_timestamp initrd_timestamp = DUAL_TIMESTAMP_NULL;
+         dual_timestamp userspace_timestamp = DUAL_TIMESTAMP_NULL;
+         dual_timestamp kernel_timestamp = DUAL_TIMESTAMP_NULL;
+         dual_timestamp security_start_timestamp = DUAL_TIMESTAMP_NULL;
+         dual_timestamp security_finish_timestamp = DUAL_TIMESTAMP_NULL;
+         static char systemd[] = "systemd";
+         bool skip_setup = false;
+         bool loaded_policy = false;
+         bool queue_default_job = false;
+         bool first_boot = false;
+         char *switch_root_dir = NULL, *switch_root_init = NULL;
+         struct rlimit saved_rlimit_nofile = RLIMIT_MAKE_CONST(0), saved_rlimit_memlock = RLIMIT_MAKE_CONST((rlim_t) -1);
+         const char *error_message = NULL;
+         redirect_telinit(argc, argv);
+         dual_timestamp_from_monotonic(&kernel_timestamp, 0);
+         dual_timestamp_get(&userspace_timestamp);
+         /* Determine if this is a reexecution or normal bootup. We do
+          * the full command line parsing much later, so let's just
+          * have a quick peek here. */
+         if (strv_find(argv+1, "--deserialize"))
+                 skip_setup = true;
+         /* If we have switched root, do all the special setup
+          * things */
+         if (strv_find(argv+1, "--switched-root"))
+                 skip_setup = false;
+         /* If we get started via the /sbin/init symlink then we are
+            called 'init'. After a subsequent reexecution we are then
+            called 'systemd'. That is confusing, hence let's call us
+            systemd right-away. */
+         program_invocation_short_name = systemd;
+         (void) prctl(PR_SET_NAME, systemd);
+         saved_argv = argv;
+         saved_argc = argc;
+         log_set_upgrade_syslog_to_journal(true);
+         if (getpid_cached() == 1) {
+                 /* Disable the umask logic */
+                 umask(0);
+                 /* Always reopen /dev/console when running as PID 1 or one of its pre-execve() children. This is
+                  * important so that we never end up logging to any foreign stderr, for example if we have to log in a
+                  * child process right before execve()'ing the actual binary, at a point in time where socket
+                  * activation stderr/stdout area already set up. */
+                 log_set_always_reopen_console(true);
+         }
+         if (getpid_cached() == 1 && detect_container() <= 0) {
+                 /* Running outside of a container as PID 1 */
+                 arg_system = true;
+                 log_set_target(LOG_TARGET_KMSG);
+                 log_open();
+                 if (in_initrd())
+                         initrd_timestamp = userspace_timestamp;
+                 if (!skip_setup) {
+                         r = mount_setup_early();
+                         if (r < 0) {
+                                 error_message = "Failed to mount early API filesystems";
+                                 goto finish;
+                         }
+                         dual_timestamp_get(&security_start_timestamp);
+                         if (mac_selinux_setup(&loaded_policy) < 0) {
+                                 error_message = "Failed to load SELinux policy";
+                                 goto finish;
+                         } else if (mac_smack_setup(&loaded_policy) < 0) {
+                                 error_message = "Failed to load SMACK policy";
+                                 goto finish;
+                         } else if (ima_setup() < 0) {
+                                 error_message = "Failed to load IMA policy";
+                                 goto finish;
+                         }
+                         dual_timestamp_get(&security_finish_timestamp);
+                 }
+                 if (mac_selinux_init() < 0) {
+                         error_message = "Failed to initialize SELinux policy";
+                         goto finish;
+                 }
+                 if (!skip_setup)
+                         initialize_clock();
+                 /* Set the default for later on, but don't actually
+                  * open the logs like this for now. Note that if we
+                  * are transitioning from the initrd there might still
+                  * be journal fd open, and we shouldn't attempt
+                  * opening that before we parsed /proc/cmdline which
+                  * might redirect output elsewhere. */
+                 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
+         } else if (getpid_cached() == 1) {
+                 /* Running inside a container, as PID 1 */
+                 arg_system = true;
+                 log_set_target(LOG_TARGET_CONSOLE);
+                 log_close_console(); /* force reopen of /dev/console */
+                 log_open();
+                 /* For later on, see above... */
+                 log_set_target(LOG_TARGET_JOURNAL);
+                 /* clear the kernel timestamp,
+                  * because we are in a container */
+                 kernel_timestamp = DUAL_TIMESTAMP_NULL;
+         } else {
+                 /* Running as user instance */
+                 arg_system = false;
+                 log_set_target(LOG_TARGET_AUTO);
+                 log_open();
+                 /* clear the kernel timestamp,
+                  * because we are not PID 1 */
+                 kernel_timestamp = DUAL_TIMESTAMP_NULL;
+         }
+         initialize_coredump(skip_setup);
+         if (arg_system) {
+                 if (fixup_environment() < 0) {
+                         error_message = "Failed to fix up PID1 environment";
+                         goto finish;
+                 }
+                 /* Try to figure out if we can use colors with the console. No
+                  * need to do that for user instances since they never log
+                  * into the console. */
+                 log_show_color(colors_enabled());
+                 r = make_null_stdio();
+                 if (r < 0)
+                         log_warning_errno(r, "Failed to redirect standard streams to /dev/null: %m");
+         }
+         r = initialize_join_controllers();
+         if (r < 0) {
+                 error_message = "Failed to initialize cgroup controllers";
+                 goto finish;
+         }
+         /* Mount /proc, /sys and friends, so that /proc/cmdline and
+          * /proc/$PID/fd is available. */
+         if (getpid_cached() == 1) {
+                 /* Load the kernel modules early. */
+                 if (!skip_setup)
+                         kmod_setup();
+                 r = mount_setup(loaded_policy);
+                 if (r < 0) {
+                         error_message = "Failed to mount API filesystems";
+                         goto finish;
+                 }
+         }
+         /* Reset all signal handlers. */
+         (void) reset_all_signal_handlers();
+         (void) ignore_signals(SIGNALS_IGNORE, -1);
+         arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U);
+         if (parse_config_file() < 0) {
+                 error_message = "Failed to parse config file";
+                 goto finish;
+         }
+         if (arg_system) {
+                 r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0);
+                 if (r < 0)
+                         log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
+         }
+         /* Note that this also parses bits from the kernel command
+          * line, including "debug". */
+         log_parse_environment();
+         if (parse_argv(argc, argv) < 0) {
+                 error_message = "Failed to parse commandline arguments";
+                 goto finish;
+         }
+         /* Initialize default unit */
+         if (!arg_default_unit) {
+                 arg_default_unit = strdup(SPECIAL_DEFAULT_TARGET);
+                 if (!arg_default_unit) {
+                         r = log_oom();
+                         error_message = "Failed to set default unit";
+                         goto finish;
+                 }
+         }
+         if (arg_action == ACTION_TEST &&
+             geteuid() == 0) {
+                 log_error("Don't run test mode as root.");
+                 goto finish;
+         }
+         if (!arg_system &&
+             arg_action == ACTION_RUN &&
+             sd_booted() <= 0) {
+                 log_error("Trying to run as user instance, but the system has not been booted with systemd.");
+                 goto finish;
+         }
+         if (arg_system &&
+             arg_action == ACTION_RUN &&
+             running_in_chroot() > 0) {
+                 log_error("Cannot be run in a chroot() environment.");
+                 goto finish;
          }
  
          if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP)) {
@@@ -724,6 -737,19 +737,19 @@@ int manager_new(UnitFileScope scope, un
          if (r < 0)
                  goto fail;
  
 -        /* Note that we do not set up the notify fd here. We do that after deserialization,
+         if (MANAGER_IS_SYSTEM(m) && test_run_flags == 0) {
+                 r = mkdir_label("/run/systemd/units", 0755);
+                 if (r < 0 && r != -EEXIST)
+                         goto fail;
+         }
+         m->taint_usr =
+                 !in_initrd() &&
+                 dir_is_empty("/usr") > 0;
++        /* Note that we do not set up neither kdbus, nor the notify fd here. We do that after deserialization,
+          * since they might have gotten serialized across the reexec. */
          *_m = m;
          return 0;
  
@@@ -957,10 -961,9 +983,10 @@@ static int manager_connect_bus(Manager 
          u = manager_get_unit(m, SPECIAL_DBUS_SERVICE);
  
          try_bus_connect =
 -                (u && SERVICE(u)->deserialized_state == SERVICE_RUNNING) &&
 -                (reexecuting ||
 -                 (MANAGER_IS_USER(m) && getenv("DBUS_SESSION_BUS_ADDRESS")));
 +                (m->kdbus_fd >= 0) ||
-                 ((u && UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) &&
++                ((u && SERVICE(u)->deserialized_state == SERVICE_RUNNING) &&
 +                 (reexecuting ||
 +                  (MANAGER_IS_USER(m) && getenv("DBUS_SESSION_BUS_ADDRESS"))));
  
          /* Try to connect to the buses, if possible. */
          return bus_init(m, try_bus_connect);
@@@ -1400,25 -1400,22 +1424,28 @@@ int manager_startup(Manager *m, FILE *s
  
          /* We might have deserialized the notify fd, but if we didn't
           * then let's create the bus now */
-         q = manager_setup_notify(m);
-         if (q < 0 && r == 0)
-                 r = q;
+         r = manager_setup_notify(m);
+         if (r < 0)
+                 /* No sense to continue without notifications, our children would fail anyway. */
+                 return r;
  
-         q = manager_setup_cgroups_agent(m);
-         if (q < 0 && r == 0)
-                 r = q;
+         r = manager_setup_cgroups_agent(m);
+         if (r < 0)
+                 /* Likewise, no sense to continue without empty cgroup notifications. */
+                 return r;
  
-         q = manager_setup_user_lookup_fd(m);
-         if (q < 0 && r == 0)
-                 r = q;
 +        /* We might have deserialized the kdbus control fd, but if we
 +         * didn't, then let's create the bus now. */
 +        manager_setup_kdbus(m);
 +        manager_connect_bus(m, !!serialization);
 +        (void) bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed);
 +
+         r = manager_setup_user_lookup_fd(m);
+         if (r < 0)
+                 /* This shouldn't fail, except if things are really broken. */
+                 return r;
  
 -        /* Let's connect to the bus now. */
 +        /* We might have deserialized the kdbus control fd, but if we didn't, then let's create the bus now. */
          (void) manager_connect_bus(m, !!serialization);
  
          (void) bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed);
@@@ -2870,9 -2868,24 +2918,24 @@@ int manager_deserialize(Manager *m, FIL
  
                          if (strv_extend(&m->deserialized_subscribed, val) < 0)
                                  log_oom();
+                 } else {
+                         ManagerTimestamp q;
  
-                 } else
-                         log_debug("Unknown serialization item '%s'", l);
+                         for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
+                                 val = startswith(l, manager_timestamp_to_string(q));
+                                 if (!val)
+                                         continue;
+                                 val = startswith(val, "-timestamp=");
+                                 if (val)
+                                         break;
+                         }
+                         if (q < _MANAGER_TIMESTAMP_MAX) /* found it */
+                                 dual_timestamp_deserialize(val, m->timestamps + q);
 -                        else if (!startswith(l, "kdbus-fd=")) /* ignore kdbus */
++                        else
+                                 log_notice("Unknown serialization item '%s'", l);
+                 }
          }
  
          for (;;) {
Simple merge
Simple merge
@@@ -91,24 -93,21 +94,24 @@@ static const MountPoint mount_table[] 
          { "devpts",      "/dev/pts",                  "devpts",     "mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC,
            NULL,          MNT_IN_CONTAINER           },
  #if ENABLE_SMACK
 -        { "tmpfs",       "/run",                      "tmpfs",      "mode=755,smackfsroot=*",  MS_NOSUID|MS_NODEV|MS_STRICTATIME,
 -          mac_smack_use, MNT_FATAL                  },
 -#endif
 -        { "tmpfs",       "/run",                      "tmpfs",      "mode=755",                MS_NOSUID|MS_NODEV|MS_STRICTATIME,
 +        { "tmpfs",      "/run",                       "tmpfs",      "mode=755,smackfstransmute=System::Run", MS_NOSUID|MS_NODEV|MS_STRICTATIME|MS_NOEXEC,
 +          mac_smack_use,  MNT_FATAL },
 +        { "tmpfs",      "/sys/fs/cgroup",             "tmpfs",      "mode=755,smackfsroot=*", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
 +          mac_smack_use,  MNT_IN_CONTAINER },
 +#else
 +        { "tmpfs",       "/run",                      "tmpfs",      "mode=755",                MS_NOSUID|MS_NODEV|MS_STRICTATIME|MS_NOEXEC,
            NULL,          MNT_FATAL|MNT_IN_CONTAINER },
 +        { "tmpfs",       "/sys/fs/cgroup",            "tmpfs",      "mode=755",                MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
 +          cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER },
 +#endif
          { "cgroup",      "/sys/fs/cgroup",            "cgroup2",    "nsdelegate",              MS_NOSUID|MS_NOEXEC|MS_NODEV,
-           cg_is_unified_wanted, MNT_IN_CONTAINER },
+           cg_is_unified_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE },
          { "cgroup",      "/sys/fs/cgroup",            "cgroup2",    NULL,                      MS_NOSUID|MS_NOEXEC|MS_NODEV,
-           cg_is_unified_wanted, MNT_IN_CONTAINER },
+           cg_is_unified_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE },
 -        { "tmpfs",       "/sys/fs/cgroup",            "tmpfs",      "mode=755",                MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
 -          cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER },
          { "cgroup",      "/sys/fs/cgroup/unified",    "cgroup2",    "nsdelegate",              MS_NOSUID|MS_NOEXEC|MS_NODEV,
-           cg_is_hybrid_wanted, MNT_IN_CONTAINER },
+           cg_is_hybrid_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE },
          { "cgroup",      "/sys/fs/cgroup/unified",    "cgroup2",    NULL,                      MS_NOSUID|MS_NOEXEC|MS_NODEV,
-           cg_is_hybrid_wanted, MNT_IN_CONTAINER },
+           cg_is_hybrid_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE },
          { "cgroup",      "/sys/fs/cgroup/systemd",    "cgroup",     "none,name=systemd,xattr", MS_NOSUID|MS_NOEXEC|MS_NODEV,
            cg_is_legacy_wanted, MNT_IN_CONTAINER     },
          { "cgroup",      "/sys/fs/cgroup/systemd",    "cgroup",     "none,name=systemd",       MS_NOSUID|MS_NOEXEC|MS_NODEV,
@@@ -615,23 -671,12 +674,23 @@@ static int service_setup_bus_name(Servi
          if (!s->bus_name)
                  return 0;
  
 -        r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, NULL, true, UNIT_DEPENDENCY_FILE);
 -        if (r < 0)
 -                return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m");
 +        if (is_kdbus_available()) {
 +                const char *n;
 +
 +                n = strjoina(s->bus_name, ".busname");
-                 r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, n, NULL, true);
++                r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, n, NULL, true, UNIT_DEPENDENCY_FILE);
 +                if (r < 0)
 +                        return log_unit_error_errno(UNIT(s), r, "Failed to add dependency to .busname unit: %m");
 +
 +        } else {
 +                /* If kdbus is not available, we know the dbus socket is required, hence pull it in, and require it */
-                 r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, NULL, true);
++                r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, NULL, true, UNIT_DEPENDENCY_FILE);
 +                if (r < 0)
 +                        return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m");
 +        }
  
 -        /* We always want to be ordered against dbus.socket if both are in the transaction. */
 +        /* Regardless if kdbus is used or not, we always want to be ordered against dbus.socket if both are in the transaction. */
-         r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_DBUS_SOCKET, NULL, true);
+         r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_DBUS_SOCKET, NULL, true, UNIT_DEPENDENCY_FILE);
          if (r < 0)
                  return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m");
  
@@@ -3440,15 -3410,14 +3469,16 @@@ static void service_notify_message
          Service *s = SERVICE(u);
          bool notify_dbus = false;
          const char *e;
+         char **i;
 +        int r;
  
          assert(u);
 +        assert(ucred);
  
 -        if (!service_notify_message_authorized(SERVICE(u), pid, tags, fds))
 +        if (!service_notify_message_authorized(SERVICE(u), ucred->pid, tags, fds))
                  return;
  
 -        if (log_get_max_level() >= LOG_DEBUG) {
 +        if (s->notify_access == NOTIFY_NONE) {
                  _cleanup_free_ char *cc = NULL;
  
                  cc = strv_join(tags, ", ");
Simple merge
Simple merge
diff --cc src/core/unit.c
Simple merge
diff --cc src/core/unit.h
@@@ -295,14 -372,28 +372,29 @@@ struct UnitStatusMessageFormats 
          const char *finished_stop_job[_JOB_RESULT_MAX];
  };
  
- typedef enum UnitSetPropertiesMode {
-         UNIT_CHECK = 0,
-         UNIT_RUNTIME = 1,
-         UNIT_PERSISTENT = 2,
- } UnitSetPropertiesMode;
+ /* Flags used when writing drop-in files or transient unit files */
+ typedef enum UnitWriteFlags {
+         /* Write a runtime unit file or drop-in (i.e. one below /run) */
+         UNIT_RUNTIME           = 1 << 0,
+         /* Write a persistent drop-in (i.e. one below /etc) */
+         UNIT_PERSISTENT        = 1 << 1,
+         /* Place this item in the per-unit-type private section, instead of [Unit] */
+         UNIT_PRIVATE           = 1 << 2,
+         /* Apply specifier escaping before writing */
+         UNIT_ESCAPE_SPECIFIERS = 1 << 3,
+         /* Apply C escaping before writing */
+         UNIT_ESCAPE_C          = 1 << 4,
+ } UnitWriteFlags;
+ /* Returns true if neither persistent, nor runtime storage is requested, i.e. this is a check invocation only */
+ #define UNIT_WRITE_FLAGS_NOOP(flags) (((flags) & (UNIT_RUNTIME|UNIT_PERSISTENT)) == 0)
  
  #include "automount.h"
 +#include "busname.h"
  #include "device.h"
  #include "path.h"
  #include "scope.h"
index e9386a7,0000000..a1eb37d
mode 100755,000000..100755
--- /dev/null
@@@ -1,363 -1,0 +1,363 @@@
-                          true, false, true, NULL);
 +/***
 +  This file is part of systemd.
 +
 +  Copyright 2013 Lennart Poettering
 +
 +  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 "alloc-util.h"
 +#include "bus-internal.h"
 +#include "bus-util.h"
 +#include "cgroup-util.h"
 +#include "conf-parser.h"
 +#include "dirent-util.h"
 +#include "fd-util.h"
 +#include "fileio.h"
 +#include "mkdir.h"
 +#include "special.h"
 +#include "unit-name.h"
 +#include "util.h"
 +
 +static const char *arg_dest_late = "/tmp", *arg_dest = "/tmp";
 +
 +static int create_dbus_files(
 +                const char *path,
 +                const char *name,
 +                const char *service,
 +                const char *exec,
 +                const char *user,
 +                const char *type) {
 +
 +        _cleanup_free_ char *b = NULL, *s = NULL, *lnk = NULL;
 +        _cleanup_fclose_ FILE *f = NULL;
 +        int r;
 +
 +        assert(path);
 +        assert(name);
 +        assert(service || exec);
 +
 +        if (!service) {
 +                _cleanup_free_ char *a = NULL;
 +
 +                s = strjoin("dbus-", name, ".service", NULL);
 +                if (!s)
 +                        return log_oom();
 +
 +                a = strjoin(arg_dest_late, "/", s, NULL);
 +                if (!a)
 +                        return log_oom();
 +
 +                f = fopen(a, "wxe");
 +                if (!f)
 +                        return log_error_errno(errno, "Failed to create %s: %m", a);
 +
 +                fprintf(f,
 +                        "# Automatically generated by systemd-dbus1-generator\n\n"
 +                        "[Unit]\n"
 +                        "SourcePath=%s\n"
 +                        "Description=DBUS1: %s\n"
 +                        "Documentation=man:systemd-dbus1-generator(8)\n\n"
 +                        "[Service]\n"
 +                        "ExecStart=%s\n"
 +                        "Type=dbus\n"
 +                        "BusName=%s\n",
 +                        path,
 +                        name,
 +                        exec,
 +                        name);
 +
 +                if (user)
 +                        fprintf(f, "User=%s\n", user);
 +
 +
 +                if (type) {
 +                        fprintf(f, "Environment=DBUS_STARTER_BUS_TYPE=%s\n", type);
 +
 +                        if (streq(type, "system"))
 +                                fprintf(f, "Environment=DBUS_STARTER_ADDRESS=" DEFAULT_SYSTEM_BUS_ADDRESS "\n");
 +                        else if (streq(type, "session")) {
 +                                char *run;
 +
 +                                run = getenv("XDG_RUNTIME_DIR");
 +                                if (!run) {
 +                                        log_error("XDG_RUNTIME_DIR not set.");
 +                                        return -EINVAL;
 +                                }
 +
 +                                fprintf(f, "Environment=DBUS_STARTER_ADDRESS="KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT "\n",
 +                                        getuid(), run);
 +                        }
 +                }
 +
 +                r = fflush_and_check(f);
 +                if (r < 0)
 +                        return log_error_errno(r, "Failed to write %s: %m", a);
 +
 +                f = safe_fclose(f);
 +
 +                service = s;
 +        }
 +
 +        b = strjoin(arg_dest_late, "/", name, ".busname", NULL);
 +        if (!b)
 +                return log_oom();
 +
 +        f = fopen(b, "wxe");
 +        if (!f)
 +                return log_error_errno(errno, "Failed to create %s: %m", b);
 +
 +        fprintf(f,
 +                "# Automatically generated by systemd-dbus1-generator\n\n"
 +                "[Unit]\n"
 +                "SourcePath=%s\n"
 +                "Description=DBUS1: %s\n"
 +                "Documentation=man:systemd-dbus1-generator(8)\n\n"
 +                "[BusName]\n"
 +                "Name=%s\n"
 +                "Service=%s\n"
 +                "AllowWorld=talk\n",
 +                path,
 +                name,
 +                name,
 +                service);
 +
 +        r = fflush_and_check(f);
 +        if (r < 0)
 +                return log_error_errno(r, "Failed to write %s: %m", b);
 +
 +        lnk = strjoin(arg_dest_late, "/" SPECIAL_BUSNAMES_TARGET ".wants/", name, ".busname", NULL);
 +        if (!lnk)
 +                return log_oom();
 +
 +        mkdir_parents_label(lnk, 0755);
 +        if (symlink(b, lnk))
 +                return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
 +
 +        return 0;
 +}
 +
 +static int add_dbus(const char *path, const char *fname, const char *type) {
 +        _cleanup_free_ char *name = NULL, *exec = NULL, *user = NULL, *service = NULL;
 +
 +        const ConfigTableItem table[] = {
 +                { "D-BUS Service", "Name", config_parse_string, 0, &name },
 +                { "D-BUS Service", "Exec", config_parse_string, 0, &exec },
 +                { "D-BUS Service", "User", config_parse_string, 0, &user },
 +                { "D-BUS Service", "SystemdService", config_parse_string, 0, &service },
 +                { },
 +        };
 +
 +        char *p;
 +        int r;
 +
 +        assert(path);
 +        assert(fname);
 +
 +        p = strjoina(path, "/", fname);
 +        r = config_parse(NULL, p, NULL,
 +                         "D-BUS Service\0",
 +                         config_item_table_lookup, table,
++                         CONFIG_PARSE_RELAXED|CONFIG_PARSE_WARN, NULL);
 +        if (r < 0)
 +                return r;
 +
 +        if (!name) {
 +                log_warning("Activation file %s lacks name setting, ignoring.", p);
 +                return 0;
 +        }
 +
 +        if (!service_name_is_valid(name)) {
 +                log_warning("Bus service name %s is not valid, ignoring.", name);
 +                return 0;
 +        }
 +
 +        if (streq(name, "org.freedesktop.systemd1")) {
 +                log_debug("Skipping %s, identified as systemd.", p);
 +                return 0;
 +        }
 +
 +        if (service) {
 +                if (!unit_name_is_valid(service, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
 +                        log_warning("Unit name %s is not valid, ignoring.", service);
 +                        return 0;
 +                }
 +                if (!endswith(service, ".service")) {
 +                        log_warning("Bus names can only activate services, ignoring %s.", p);
 +                        return 0;
 +                }
 +        } else {
 +                if (!exec || streq(exec, "/bin/false")) {
 +                        log_warning("Neither service name nor binary path specified, ignoring %s.", p);
 +                        return 0;
 +                }
 +
 +                if (exec[0] != '/') {
 +                        log_warning("Exec= in %s does not start with an absolute path, ignoring.", p);
 +                        return 0;
 +                }
 +        }
 +
 +        return create_dbus_files(p, name, service, exec, user, type);
 +}
 +
 +static int parse_dbus_fragments(const char *path, const char *type) {
 +        _cleanup_closedir_ DIR *d = NULL;
 +        struct dirent *de;
 +        int r;
 +
 +        assert(path);
 +        assert(type);
 +
 +        d = opendir(path);
 +        if (!d) {
 +                if (errno == -ENOENT)
 +                        return 0;
 +
 +                return log_error_errno(errno, "Failed to enumerate D-Bus activated services: %m");
 +        }
 +
 +        r = 0;
 +        FOREACH_DIRENT(de, d, goto fail) {
 +                int q;
 +
 +                if (!endswith(de->d_name, ".service"))
 +                        continue;
 +
 +                q = add_dbus(path, de->d_name, type);
 +                if (q < 0)
 +                        r = q;
 +        }
 +
 +        return r;
 +
 +fail:
 +        return log_error_errno(errno, "Failed to read D-Bus services directory: %m");
 +}
 +
 +static int link_busnames_target(const char *units) {
 +        const char *f, *t;
 +
 +        f = strjoina(units, "/" SPECIAL_BUSNAMES_TARGET);
 +        t = strjoina(arg_dest, "/" SPECIAL_BASIC_TARGET ".wants/" SPECIAL_BUSNAMES_TARGET);
 +
 +        mkdir_parents_label(t, 0755);
 +        if (symlink(f, t) < 0)
 +                return log_error_errno(errno, "Failed to create symlink %s: %m", t);
 +
 +        return 0;
 +}
 +
 +static int create_compatibility(const char *units, const char *type) {
 +        const char *t;
 +        _cleanup_fclose_ FILE *f = NULL;
 +        int r;
 +
 +        t = strjoina(arg_dest, "/" SPECIAL_DBUS_SERVICE);
 +        if (!t)
 +                return log_oom();
 +
 +        f = fopen(t, "wxe");
 +        if (!f)
 +                return log_error_errno(errno, "Failed to create %s: %m", t);
 +
 +        fprintf(f,
 +                "# Automatically generated by systemd-dbus1-generator\n\n"
 +                "[Unit]\n"
 +                "Description=DBUS1: dbus.service for kdbus compatibility\n"
 +                "[Service]\n"
 +                "ExecStart=/bin/true\n"
 +                "RemainAfterExit=yes\n");
 +
 +        r = fflush_and_check(f);
 +        if (r < 0)
 +                return log_error_errno(r, "Failed to write %s: %m", t);
 +
 +        f = safe_fclose(f);
 +
 +
 +        t = strjoina(arg_dest, "/" SPECIAL_DBUS_SOCKET);
 +        if (!t)
 +                return log_oom();
 +
 +        f = fopen(t, "wxe");
 +        if (!f)
 +                return log_error_errno(errno, "Failed to create %s: %m", t);
 +
 +        fprintf(f,
 +                "# Automatically generated by systemd-dbus1-generator\n\n"
 +                "[Unit]\n"
 +                "Description=DBUS1: dbus.socket for kdbus compatibility\n"
 +                "[Socket]\n"
 +                "SmackLabelIPIn=^\n"
 +                "ListenStream=@/tmp/.kdbus_bus_%s_%d\n", type, getuid());
 +
 +
 +        r = fflush_and_check(f);
 +        if (r < 0)
 +                return log_error_errno(r, "Failed to write %s: %m", t);
 +
 +        f = safe_fclose(f);
 +
 +        return 0;
 +}
 +
 +int main(int argc, char *argv[]) {
 +        const char *path, *type, *units;
 +        int r, q;
 +
 +        if (argc > 1 && argc != 4) {
 +                log_error("This program takes three or no arguments.");
 +                return EXIT_FAILURE;
 +        }
 +
 +        if (argc > 1) {
 +                arg_dest = argv[1];
 +                arg_dest_late = argv[3];
 +        }
 +
 +        log_set_target(LOG_TARGET_SAFE);
 +        log_parse_environment();
 +        log_open();
 +
 +        umask(0022);
 +
 +        if (!is_kdbus_available())
 +                return 0;
 +
 +        r = cg_pid_get_owner_uid(0, NULL);
 +        if (r >= 0) {
 +                path = "/usr/share/dbus-1/services";
 +                type = "session";
 +                units = USER_DATA_UNIT_PATH;
 +        } else if (r == -ENXIO) {
 +                path = "/usr/share/dbus-1/system-services";
 +                type = "system";
 +                units = SYSTEM_DATA_UNIT_PATH;
 +        } else
 +                return log_error_errno(r, "Failed to determine whether we are running as user or system instance: %m");
 +
 +        r = parse_dbus_fragments(path, type);
 +
 +        /* FIXME: One day this should just be pulled in statically from basic.target */
 +        q = link_busnames_target(units);
 +        if (q < 0)
 +                r = q;
 +
 +        q = create_compatibility(units, type);
 +        if (q < 0)
 +                r = q;
 +
 +        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 +}
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index e599427,0000000..7f6d7f4
mode 100644,000000..100644
--- /dev/null
@@@ -1,210 -1,0 +1,210 @@@
-         r = bus_message_seal(m, 55, 99*USEC_PER_SEC);
 +/***
 +  This file is part of systemd.
 +
 +  Copyright 2013 Lennart Poettering
 +
 +  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 <sys/mman.h>
 +
 +#include "sd-bus.h"
 +
 +#include "alloc-util.h"
 +#include "bus-dump.h"
 +#include "bus-kernel.h"
 +#include "bus-message.h"
 +#include "fd-util.h"
 +#include "log.h"
 +#include "memfd-util.h"
 +#include "string-util.h"
 +#include "util.h"
 +
 +#define FIRST_ARRAY 17
 +#define SECOND_ARRAY 33
 +
 +#define STRING_SIZE 123
 +
 +int main(int argc, char *argv[]) {
 +        _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL;
 +        const char *unique;
 +        uint8_t *p;
 +        sd_bus *a, *b;
 +        int r, bus_ref;
 +        sd_bus_message *m;
 +        int f;
 +        uint64_t sz;
 +        uint32_t u32;
 +        size_t i, l;
 +        char *s;
 +        _cleanup_close_ int sfd = -1;
 +
 +        log_set_max_level(LOG_DEBUG);
 +
 +        assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid_cached()) >= 0);
 +
 +        bus_ref = bus_kernel_create_bus(name, false, &bus_name);
 +        if (bus_ref == -ENOENT)
 +                return EXIT_TEST_SKIP;
 +
 +        assert_se(bus_ref >= 0);
 +
 +        address = strappend("kernel:path=", bus_name);
 +        assert_se(address);
 +
 +        r = sd_bus_new(&a);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_new(&b);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_set_address(a, address);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_set_address(b, address);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_start(a);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_start(b);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_get_unique_name(a, &unique);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_message_new_method_call(b, &m, unique, "/a/path", "an.inter.face", "AMethod");
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_message_open_container(m, 'r', "aysay");
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_message_append_array_space(m, 'y', FIRST_ARRAY, (void**) &p);
 +        assert_se(r >= 0);
 +
 +        p[0] = '<';
 +        memset(p+1, 'L', FIRST_ARRAY-2);
 +        p[FIRST_ARRAY-1] = '>';
 +
 +        f = memfd_new_and_map(NULL, STRING_SIZE, (void**) &s);
 +        assert_se(f >= 0);
 +
 +        s[0] = '<';
 +        for (i = 1; i < STRING_SIZE-2; i++)
 +                s[i] = '0' + (i % 10);
 +        s[STRING_SIZE-2] = '>';
 +        s[STRING_SIZE-1] = 0;
 +        munmap(s, STRING_SIZE);
 +
 +        r = memfd_get_size(f, &sz);
 +        assert_se(r >= 0);
 +        assert_se(sz == STRING_SIZE);
 +
 +        r = sd_bus_message_append_string_memfd(m, f, 0, (uint64_t) -1);
 +        assert_se(r >= 0);
 +
 +        close(f);
 +
 +        f = memfd_new_and_map(NULL, SECOND_ARRAY, (void**) &p);
 +        assert_se(f >= 0);
 +
 +        p[0] = '<';
 +        memset(p+1, 'P', SECOND_ARRAY-2);
 +        p[SECOND_ARRAY-1] = '>';
 +        munmap(p, SECOND_ARRAY);
 +
 +        r = memfd_get_size(f, &sz);
 +        assert_se(r >= 0);
 +        assert_se(sz == SECOND_ARRAY);
 +
 +        r = sd_bus_message_append_array_memfd(m, 'y', f, 0, (uint64_t) -1);
 +        assert_se(r >= 0);
 +
 +        close(f);
 +
 +        r = sd_bus_message_close_container(m);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_message_append(m, "u", 4711);
 +        assert_se(r >= 0);
 +
 +        assert_se((sfd = memfd_new_and_map(NULL, 6, (void**) &p)) >= 0);
 +        memcpy(p, "abcd\0", 6);
 +        munmap(p, 6);
 +        assert_se(sd_bus_message_append_string_memfd(m, sfd, 1, 4) >= 0);
 +
++        r = sd_bus_message_seal(m, 55, 99*USEC_PER_SEC);
 +        assert_se(r >= 0);
 +
 +        bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
 +
 +        r = sd_bus_send(b, m, NULL);
 +        assert_se(r >= 0);
 +
 +        sd_bus_message_unref(m);
 +
 +        r = sd_bus_process(a, &m);
 +        assert_se(r > 0);
 +
 +        bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
 +        sd_bus_message_rewind(m, true);
 +
 +        r = sd_bus_message_enter_container(m, 'r', "aysay");
 +        assert_se(r > 0);
 +
 +        r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l);
 +        assert_se(r > 0);
 +        assert_se(l == FIRST_ARRAY);
 +
 +        assert_se(p[0] == '<');
 +        for (i = 1; i < l-1; i++)
 +                assert_se(p[i] == 'L');
 +        assert_se(p[l-1] == '>');
 +
 +        r = sd_bus_message_read(m, "s", &s);
 +        assert_se(r > 0);
 +
 +        assert_se(s[0] == '<');
 +        for (i = 1; i < STRING_SIZE-2; i++)
 +                assert_se(s[i] == (char) ('0' + (i % 10)));
 +        assert_se(s[STRING_SIZE-2] == '>');
 +        assert_se(s[STRING_SIZE-1] == 0);
 +
 +        r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l);
 +        assert_se(r > 0);
 +        assert_se(l == SECOND_ARRAY);
 +
 +        assert_se(p[0] == '<');
 +        for (i = 1; i < l-1; i++)
 +                assert_se(p[i] == 'P');
 +        assert_se(p[l-1] == '>');
 +
 +        r = sd_bus_message_exit_container(m);
 +        assert_se(r > 0);
 +
 +        r = sd_bus_message_read(m, "u", &u32);
 +        assert_se(r > 0);
 +        assert_se(u32 == 4711);
 +
 +        r = sd_bus_message_read(m, "s", &s);
 +        assert_se(r > 0);
 +        assert_se(streq_ptr(s, "bcd"));
 +
 +        sd_bus_message_unref(m);
 +
 +        sd_bus_unref(a);
 +        sd_bus_unref(b);
 +
 +        return 0;
 +}
Simple merge
Simple merge
@@@ -21,7 -22,7 +22,8 @@@
  #include <string.h>
  #include <sys/mount.h>
  #include <unistd.h>
+ #include <stdio_ext.h>
 +#include <sys/xattr.h>
  
  #include "alloc-util.h"
  #include "bus-common-errors.h"
@@@ -330,38 -332,6 +333,38 @@@ int user_load(User *u) 
          return r;
  }
  
-         r = mkdir_safe_label(t, 0750, u->uid, system_share_gid);
 +static int user_mkdir_system_share_path(User *u) {
 +        int r;
 +        gid_t system_share_gid;
 +        _cleanup_free_ char *t = NULL;
 +        const char *system_share_group = "system_share";
 +
 +        r = get_group_creds(&system_share_group, &system_share_gid);
 +        if (r < 0)
 +                return r;
 +
 +        /* mount option "gid=system_share" doesn't work. So, we have to modify gid here*/
 +        r = chmod_and_chown(u->runtime_path, 0750, u->uid, system_share_gid);
 +        if (r < 0)
 +                return log_error_errno(r, "Failed to change runtime directory ownership and mode: %m");
 +
 +        r = asprintf(&t, "/run/user/"UID_FMT"/system_share", u->uid);
 +        if (r < 0)
 +                return log_oom();
 +
++        r = mkdir_safe_label(t, 0750, u->uid, system_share_gid, false);
 +        if (r < 0)
 +                return log_error_errno(r, "Failed to create '%s': %m", t);
 +
 +        if (mac_smack_use()) {
 +                r = lsetxattr(t, "security.SMACK64", SMACK_STAR_LABEL, strlen(SMACK_STAR_LABEL), 0);
 +                if (r < 0)
 +                        return log_error_errno(r, "Failed to apply smack label * to '%s': %m", t);
 +        }
 +
 +        return 0;
 +}
 +
  static int user_mkdir_runtime_path(User *u) {
          int r;
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -431,46 -459,14 +459,52 @@@ static void test_safe_atoi16(void) 
  
          r = safe_atoi16("123x", &l);
          assert_se(r == -EINVAL);
+         r = safe_atoi16("12.3", &l);
+         assert_se(r == -EINVAL);
+         r = safe_atoi16("", &l);
+         assert_se(r == -EINVAL);
  }
  
 +static void test_safe_atoux16(void) {
 +        int r;
 +        uint16_t l;
 +
 +        r = safe_atoux16("1234", &l);
 +        assert_se(r == 0);
 +        assert_se(l == 0x1234);
 +
 +        r = safe_atoux16("abcd", &l);
 +        assert_se(r == 0);
 +        assert_se(l == 0xabcd);
 +
 +        r = safe_atoux16("  1234", &l);
 +        assert_se(r == 0);
 +        assert_se(l == 0x1234);
 +
 +        r = safe_atoux16("12345", &l);
 +        assert_se(r == -ERANGE);
 +
 +        r = safe_atoux16("-1", &l);
 +        assert_se(r == -ERANGE);
 +
 +        r = safe_atoux16("  -1", &l);
 +        assert_se(r == -ERANGE);
 +
 +        r = safe_atoux16("junk", &l);
 +        assert_se(r == -EINVAL);
 +
 +        r = safe_atoux16("123x", &l);
 +        assert_se(r == -EINVAL);
 +
 +        r = safe_atoux16("12.3", &l);
 +        assert_se(r == -EINVAL);
 +
 +        r = safe_atoux16("", &l);
 +        assert_se(r == -EINVAL);
 +}
 +
  static void test_safe_atou64(void) {
          int r;
          uint64_t l;
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1,18 -1,38 +1,45 @@@
+ # SPDX-License-Identifier: LGPL-2.1+
+ #
+ # Copyright 2017 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/>.
  test_data_files = '''
          a.service
-         basic.target
          b.service
+         basic.target
++        bus-policy/hello.conf
++        bus-policy/methods.conf
++        bus-policy/ownerships.conf
++        bus-policy/signals.conf
++        bus-policy/check-own-rules.conf
++        bus-policy/many-rules.conf
++        bus-policy/test.conf
          c.service
-         daughter.service
          d.service
-         end.service
+         daughter.service
          e.service
+         end.service
          f.service
-         grandchild.service
          g.service
+         grandchild.service
+         h.service
          hello-after-sleep.target
          hello.service
-         h.service
+         hwdb/10-bad.hwdb
+         journal-data/journal-1.txt
+         journal-data/journal-2.txt
          parent-deep.slice
          parent.slice
          sched_idle_bad.service
@@@ -20,7 -21,7 +21,7 @@@ if ! ROOTLIBDIR=$(pkg-config --variable
      ROOTLIBDIR=/usr/lib/systemd
  fi
  
- BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm chmod chown ln"
 -BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false"
++BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm chmod chown ln true false"
  DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find"
  
  STATEDIR="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))"
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1,5 -1,23 +1,22 @@@
+ # SPDX-License-Identifier: LGPL-2.1+
+ #
+ # Copyright 2017 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/>.
  units = [
          ['basic.target',                        ''],
 -        ['bluetooth.target',                    ''],
          ['cryptsetup-pre.target',               'HAVE_LIBCRYPTSETUP'],
          ['cryptsetup.target',                   'HAVE_LIBCRYPTSETUP',
           'sysinit.target.wants/'],
@@@ -211,18 -225,11 +227,18 @@@ in_units = 
           'multi-user.target.wants/ graphical.target.wants/ rescue.target.wants/'],
          ['systemd-update-utmp.service',          'ENABLE_UTMP',
           'sysinit.target.wants/'],
-         ['systemd-user-sessions.service',        '',
+         ['systemd-user-sessions.service',        'HAVE_PAM',
           'multi-user.target.wants/'],
 -        ['systemd-vconsole-setup.service',       'ENABLE_VCONSOLE'],
 +        ['systemd-vconsole-setup.service',       'ENABLE_VCONSOLE',
 +         'sysinit.target.wants/'],
          ['systemd-volatile-root.service',        ''],
          ['user@.service',                        ''],
 +        ['booting-done.service',                 '',
 +         'delayed.target.wants/'],
 +        ['system-delayed-target-done.service',   '',
 +         'delayed.target.wants/'],
 +        ['system-default-target-done.service',  '', 'graphical.target.wants/'],
 +        ['system-delayed-target-trigger.service', '', 'graphical.target.wants/'],
  ]
  
  m4_units = [
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -19,9 -21,9 +21,10 @@@ KillMode=mixe
  Type=notify
  RestartForceExitStatus=133
  SuccessExitStatus=133
+ WatchdogSec=3min
  Slice=machine.slice
  Delegate=yes
 +SmackProcessLabel=System
  TasksMax=16384
  
  # Enforce a strict device policy, similar to the one nspawn configures when it
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -16,5 -18,5 +18,6 @@@ Before=shutdown.targe
  [Service]
  Type=oneshot
  ExecStart=@rootbindir@/systemd-tmpfiles --clean
+ SuccessExitStatus=65
  IOSchedulingClass=idle
 +SmackProcessLabel=System::Privileged
@@@ -18,4 -20,4 +20,5 @@@ ConditionCapability=CAP_SYS_MODUL
  Type=oneshot
  RemainAfterExit=yes
  ExecStart=@rootbindir@/systemd-tmpfiles --prefix=/dev --create --boot
+ SuccessExitStatus=65
 +SmackProcessLabel=System::Privileged
@@@ -18,4 -20,4 +20,5 @@@ RefuseManualStop=ye
  Type=oneshot
  RemainAfterExit=yes
  ExecStart=@rootbindir@/systemd-tmpfiles --create --remove --boot --exclude-prefix=/dev
+ SuccessExitStatus=65
 +SmackProcessLabel=System::Privileged
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1,6 -1,23 +1,23 @@@
+ # SPDX-License-Identifier: LGPL-2.1+
+ #
+ # Copyright 2017 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/>.
  units = [
          'basic.target',
 -        'bluetooth.target',
 +        'busnames.target',
          'default.target',
          'exit.target',
          'graphical-session-pre.target',
          'sockets.target',
          'sound.target',
          'timers.target',
+         'systemd-tmpfiles-clean.timer',
  ]
  
 +units += [
 +          'delayed.target',
 +          'user-delayed-target-trigger.service',
 +          'user-default-target-done.service',
 +          'user-delayed-target-done.service',
 +]
 +
  foreach file : units
          install_data(file,
                       install_dir : userunitdir)
  endforeach
  
 +meson.add_install_script('../meson-add-wants.sh', userunitdir, 'default.target.wants/', 'user-delayed-target-trigger.service')
 +meson.add_install_script('../meson-add-wants.sh', userunitdir, 'default.target.wants/', 'user-default-target-done.service')
 +meson.add_install_script('../meson-add-wants.sh', userunitdir, 'delayed.target.wants/', 'user-delayed-target-done.service')
 +
  in_units = [
          'systemd-exit.service',
+         'systemd-tmpfiles-clean.service',
+         'systemd-tmpfiles-setup.service',
  ]
  
  foreach file : in_units
@@@ -11,18 -13,11 +13,18 @@@ After=systemd-user-sessions.servic
  
  [Service]
  User=%i
 +Group=users
  PAMName=systemd-user
 -Type=notify
 +Type=simple
  ExecStart=-@rootlibexecdir@/systemd --user
 +SmackProcessLabel=User
  Slice=user-%i.slice
  KillMode=mixed
- Delegate=yes
+ Delegate=pids cpu
  TasksMax=infinity
 +Environment=DBUS_SESSION_BUS_ADDRESS=kernel:path=/sys/fs/kdbus/%i-user/bus;unix:path=/run/user/%i/bus
 +Environment=XDG_RUNTIME_DIR=/run/user/%i
 +Capabilities=cap_sys_admin,cap_mac_admin,cap_setgid,cap_dac_override=i
 +SecureBits=keep-caps
 +TimeoutStartSec=infinity
  TimeoutStopSec=120s