summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am62
-rw-r--r--TODO94
-rw-r--r--configure.ac10
-rw-r--r--man/daemon.xml2
-rw-r--r--man/hostname.xml13
-rw-r--r--man/machine-id.xml8
-rw-r--r--man/machine-info.xml147
-rw-r--r--man/os-release.xml19
-rw-r--r--man/systemd-ask-password.xml183
-rw-r--r--man/systemd.mount.xml2
-rw-r--r--man/systemd.path.xml22
-rw-r--r--man/systemd.service.xml2
-rw-r--r--man/systemd.socket.xml33
-rw-r--r--man/systemd.unit.xml26
-rw-r--r--src/ask-password-api.c12
-rw-r--r--src/ask-password.c15
-rw-r--r--src/automount.c2
-rw-r--r--src/cgroup.c14
-rw-r--r--src/cgroup.h4
-rw-r--r--src/cgroups-agent.c2
-rw-r--r--src/cryptsetup-generator.c51
-rw-r--r--src/cryptsetup.c9
-rw-r--r--src/dbus-automount.c3
-rw-r--r--src/dbus-common.c447
-rw-r--r--src/dbus-common.h119
-rw-r--r--src/dbus-device.c3
-rw-r--r--src/dbus-execute.c41
-rw-r--r--src/dbus-execute.h38
-rw-r--r--src/dbus-job.c10
-rw-r--r--src/dbus-manager.c113
-rw-r--r--src/dbus-mount.c13
-rw-r--r--src/dbus-path.c17
-rw-r--r--src/dbus-service.c3
-rw-r--r--src/dbus-snapshot.c4
-rw-r--r--src/dbus-socket.c3
-rw-r--r--src/dbus-swap.c6
-rw-r--r--src/dbus-target.c3
-rw-r--r--src/dbus-timer.c9
-rw-r--r--src/dbus-unit.c58
-rw-r--r--src/dbus-unit.h53
-rw-r--r--src/dbus.c459
-rw-r--r--src/dbus.h108
-rw-r--r--src/def.h2
-rw-r--r--src/device.c3
-rw-r--r--src/execute.c76
-rw-r--r--src/getty-generator.c1
-rw-r--r--src/gnome-ask-password-agent.vala2
-rw-r--r--src/hostname-setup.c41
-rw-r--r--src/hostnamed.c704
-rw-r--r--src/initctl.c5
-rw-r--r--src/job.c61
-rw-r--r--src/load-fragment.c35
-rw-r--r--src/locale-setup.c4
-rw-r--r--src/log.c10
-rw-r--r--src/logger.c5
-rw-r--r--src/manager.c94
-rw-r--r--src/manager.h1
-rw-r--r--src/mount-setup.c29
-rw-r--r--src/mount.c133
-rw-r--r--src/nspawn.c9
-rw-r--r--src/org.freedesktop.hostname1.conf27
-rw-r--r--src/org.freedesktop.hostname1.policy49
-rw-r--r--src/org.freedesktop.hostname1.service12
-rw-r--r--src/org.freedesktop.systemd1.policy.in4
-rw-r--r--src/pam-module.c43
-rw-r--r--src/path.c39
-rw-r--r--src/path.h3
-rw-r--r--src/readahead-common.c1
-rw-r--r--src/reply-password.c2
-rw-r--r--src/service.c2
-rw-r--r--src/socket-util.c279
-rw-r--r--src/socket-util.h11
-rw-r--r--src/socket.c126
-rw-r--r--src/socket.h1
-rw-r--r--src/strv.c50
-rw-r--r--src/strv.h1
-rw-r--r--src/swap.c3
-rw-r--r--src/systemctl-bash-completion.sh2
-rw-r--r--src/systemctl.c17
-rwxr-xr-xsrc/systemd-analyze40
-rw-r--r--src/tmpfiles.c48
-rw-r--r--src/tty-ask-password-agent.c33
-rw-r--r--src/unit.c43
-rw-r--r--src/unit.h9
-rw-r--r--src/util.c195
-rw-r--r--src/util.h13
-rw-r--r--src/vconsole-setup.c38
-rw-r--r--tmpfiles.d/systemd.conf2
-rw-r--r--units/.gitignore1
-rw-r--r--units/emergency.service2
-rw-r--r--units/fsck-root.service.in2
-rw-r--r--units/fsck@.service.in2
-rw-r--r--units/local-fs.target2
-rw-r--r--units/quotacheck.service.in2
-rw-r--r--units/remount-rootfs.service2
-rw-r--r--units/rescue.service.m47
-rw-r--r--units/syslog.target5
-rw-r--r--units/systemd-ask-password-console.path1
-rw-r--r--units/systemd-ask-password-plymouth.path1
-rw-r--r--units/systemd-ask-password-wall.path1
-rw-r--r--units/systemd-hostnamed.service.in17
-rw-r--r--units/systemd-kmsg-syslogd.service.in2
-rw-r--r--units/systemd-logger.service.in2
-rw-r--r--units/systemd-logger.socket7
-rw-r--r--units/systemd-shutdownd.service.in2
-rw-r--r--units/systemd-update-utmp-runlevel.service.in1
-rw-r--r--units/systemd-update-utmp-shutdown.service.in1
108 files changed, 3416 insertions, 1195 deletions
diff --git a/.gitignore b/.gitignore
index be44cb60bb..5669d740ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+systemd-hostnamed
systemd-binfmt
systemd-getty-generator
systemd-nspawn
diff --git a/Makefile.am b/Makefile.am
index 2f08ceb173..0aaa1e45c3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -90,6 +90,12 @@ AM_CPPFLAGS += \
-DKBD_SETFONT=\"/bin/setfont\" \
-DDEFAULT_FONT=\"LatArCyrHeb-16\"
else
+if TARGET_MEEGO
+AM_CPPFLAGS += \
+ -DKBD_LOADKEYS=\"/bin/loadkeys\" \
+ -DKBD_SETFONT=\"/bin/setfont\" \
+ -DDEFAULT_FONT=\"LatArCyrHeb-16\"
+else
AM_CPPFLAGS += \
-DKBD_LOADKEYS=\"/bin/loadkeys\" \
-DKBD_SETFONT=\"/bin/setfont\" \
@@ -98,6 +104,7 @@ endif
endif
endif
endif
+endif
rootbin_PROGRAMS = \
systemd \
@@ -144,7 +151,8 @@ rootlibexec_PROGRAMS = \
systemd-ac-power \
systemd-detect-virt \
systemd-sysctl \
- systemd-binfmt
+ systemd-binfmt \
+ systemd-hostnamed
systemgenerator_PROGRAMS = \
systemd-getty-generator
@@ -177,10 +185,12 @@ dist_pkgsysconf_DATA = \
src/system.conf
dist_dbuspolicy_DATA = \
- src/org.freedesktop.systemd1.conf
+ src/org.freedesktop.systemd1.conf \
+ src/org.freedesktop.hostname1.conf
dist_dbussystemservice_DATA = \
- src/org.freedesktop.systemd1.service
+ src/org.freedesktop.systemd1.service \
+ src/org.freedesktop.hostname1.service
dist_udevrules_DATA = \
src/99-systemd.rules
@@ -282,6 +292,7 @@ nodist_systemunit_DATA = \
units/systemd-initctl.service \
units/systemd-logger.service \
units/systemd-shutdownd.service \
+ units/systemd-hostnamed.service \
units/systemd-kmsg-syslogd.service \
units/systemd-modules-load.service \
units/systemd-vconsole-setup.service \
@@ -326,6 +337,7 @@ EXTRA_DIST = \
units/systemd-initctl.service.in \
units/systemd-logger.service.in \
units/systemd-shutdownd.service.in \
+ units/systemd-hostnamed.service.in \
units/systemd-kmsg-syslogd.service.in \
units/systemd-modules-load.service.in \
units/systemd-vconsole-setup.service.in \
@@ -406,9 +418,12 @@ dist_doc_DATA = \
pkgconfigdata_DATA = \
systemd.pc
-polkitpolicy_DATA = \
+nodist_polkitpolicy_DATA = \
src/org.freedesktop.systemd1.policy
+dist_polkitpolicy_DATA = \
+ src/org.freedesktop.hostname1.policy
+
noinst_LTLIBRARIES = \
libsystemd-basic.la \
libsystemd-core.la \
@@ -481,7 +496,8 @@ libsystemd_core_la_SOURCES = \
src/namespace.c \
src/tcpwrap.c \
src/cgroup-util.c \
- src/condition.c
+ src/condition.c \
+ src/dbus-common.c
libsystemd_core_la_CFLAGS = \
$(AM_CFLAGS) \
@@ -570,9 +586,11 @@ MANPAGES = \
man/vconsole.conf.5 \
man/locale.conf.5 \
man/os-release.5 \
+ man/machine-info.5 \
man/modules-load.d.5 \
man/binfmt.d.5 \
- man/sysctl.d.5
+ man/sysctl.d.5 \
+ man/systemd-ask-password.1
MANPAGES_ALIAS = \
man/reboot.8 \
@@ -752,6 +770,19 @@ systemd_shutdownd_LDADD = \
libsystemd-basic.la \
libsystemd-daemon.la
+systemd_hostnamed_SOURCES = \
+ src/hostnamed.c \
+ src/dbus-common.c
+
+systemd_hostnamed_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(DBUS_CFLAGS)
+
+systemd_hostnamed_LDADD = \
+ libsystemd-basic.la \
+ libsystemd-daemon.la \
+ $(DBUS_LIBS)
+
systemd_shutdown_SOURCES = \
src/mount-setup.c \
src/umount.c \
@@ -1344,9 +1375,10 @@ install-data-hook:
$(LN_S) graphical.target runlevel5.target && \
$(LN_S) reboot.target runlevel6.target )
( cd $(DESTDIR)$(systemunitdir) && \
- rm -f default.target ctrl-alt-del.target && \
+ rm -f default.target ctrl-alt-del.target dbus-org.freedesktop.hostname1.service && \
$(LN_S) graphical.target default.target && \
- $(LN_S) reboot.target ctrl-alt-del.target )
+ $(LN_S) reboot.target ctrl-alt-del.target && \
+ $(LN_S) systemd-hostnamed.service dbus-org.freedesktop.hostname1.service )
( cd $(DESTDIR)$(systemunitdir)/multi-user.target.wants && \
rm -f getty.target systemd-user-sessions.service systemd-ask-password-wall.path && \
$(LN_S) ../getty.target getty.target && \
@@ -1429,6 +1461,20 @@ if HAVE_PLYMOUTH
rm -f plymouth-halt.service && \
$(LN_S) ../plymouth-halt.service plymouth-halt.service )
endif
+if TARGET_MEEGO
+ $(MKDIR_P) -m 0755 $(DESTDIR)$(systemunitdir)/final.target.wants
+ ( cd $(DESTDIR)$(systemunitdir)/multi-user.target.wants && \
+ rm -f network.target && \
+ $(LN_S) $(systemunitdir)/network.target network.target )
+ ( cd $(DESTDIR)$(pkgsysconfdir)/system/sysinit.target.wants && \
+ rm -f * )
+ ( cd $(DESTDIR)$(pkgsysconfdir)/system/local-fs.target.wants && \
+ rm -f * )
+ ( cd $(DESTDIR)$(pkgsysconfdir)/system/multi-user.target.wants && \
+ rm -f * )
+ ( cd $(DESTDIR)$(pkgsysconfdir)/system/getty.target.wants && \
+ rm -f * )
+endif
if TARGET_FEDORA
$(MKDIR_P) -m 0755 $(DESTDIR)$(systemunitdir)/final.target.wants
diff --git a/TODO b/TODO
index e8c1388ed6..6b2de73781 100644
--- a/TODO
+++ b/TODO
@@ -2,46 +2,57 @@ F15:
* swap units that are activated by one name but shown in the kernel under another are semi-broken
-* isolate multi-user.target doesn't start a getty@tty1 if we run it from graphical.target
- https://bugzilla.redhat.com/show_bug.cgi?id=688661
+* Fix assert http://lists.freedesktop.org/archives/systemd-devel/2011-April/001910.html
+
+* 0595f9a1c182a84581749823ef47c5f292e545f9 is borked, freezes shutdown
+ (path: after installing inotify watches, recheck file again to fix race)
+
+F15 External:
* NFS, networkmanager ordering issue (PENDING)
* NM should pull in network.target (PENDING)
https://bugzilla.redhat.com/show_bug.cgi?id=692008
-* ntpd should pull in time-sync.target. (PENDING)
+* bluetooth should be possible to disable (PENDING)
-* add fstab fields to add wait timeouts, change Wants to Requires by local-fs.target
+* get writev() /dev/kmsg support into the F15 kernel
+ https://lkml.org/lkml/2011/4/6/473
+ patched merged into -mm
-* hook emergency.target into local-fs.target in some way as OnFailure with isolate
+* fix sd_is_socket() invocation in dbus
-* bind mounts are ignored
- https://bugzilla.redhat.com/show_bug.cgi?id=682662
+* New CK release, with sysinit.target dropping and TTY loop
-* 0595f9a1c182a84581749823ef47c5f292e545f9 is borked, freezes shutdown
- (path: after installing inotify watches, recheck file again to fix race)
+* New Avahi package, enable it by default
-* bluetooth should be possible to disable
-
-* fix alsa mixer restore to not print error when no config is stored
+* make anaconda write timeout=0 for encrypted devices
Features:
-* don't trim empty cgroups
- https://bugzilla.redhat.com/show_bug.cgi?id=678555
+* Maybe merge nss-myhostname into systemd?
-* serialize used job ids and max job id
+* maybe lower default timeout to 2min?
-* show enablement status in systemctl status
+* GC unreferenced jobs (such as .device jobs)
+
+* support wildcard expansion in ListeStream= and friends
+
+* avoid DefaultStandardOutput=syslog to have any effect on StandardInput=socket services
+
+* use pivot_root on shutdown so that we can unmount the root directory.
+
+* fix alsa mixer restore to not print error when no config is stored
-* expose monotonic timestamps on the bus and make systemd-analyze use it
+* show enablement status in systemctl status
* write blog stories about:
- - chroot, nspawn and friends
- - the blame game: systemd-analyze
- enabling dbus services
- status update
+ - the new configuration files
+ - you are a distro: why switch?
+
+* maybe add tiny dbus services similar to hostnamed for locale and wallclock/timezone?
* allow port = 0 in .socket units
@@ -49,16 +60,13 @@ Features:
* introduce /usr/lib/binfmt.d/, /usr/lib/tmpfiles.d/
-* in pam_systemd: don't rely on /proc/self/loginuid in a container
-
* take BSD file lock on tty devices when using them?
-* tmpfiles should allow two identical lines
- https://bugzilla.redhat.com/show_bug.cgi?id=690253
-
* avoid any flag files, or readahead files in /, we need to support r/o /
or / on tmpfs like Android setups.
+* move readahead files into /var, look for them with .path units
+
* teach dbus to activate all services it finds in /etc/systemd/services/org-*.service
* get process transport into dbus for systemctl -P/-H
@@ -70,22 +78,25 @@ Features:
* Find a way to replace /var/run, /var/lock directories with
symlinks during an RPM package upgrade (filesystem.rpm or systemd.rpm).
- We soon want to get rid of var-run.mount var-lock.mount units.
+ (lua code to create symlinks right away for new installations is in filesytem.rpm now)
+ We soon want to get rid of var-run.mount var-lock.mount units:
+ if mountpoint /run ; then
+ umount /var/run || :
+ else
+ mount --move /var/run /run || mount --bind /var/run /run
+ fi
+ mv /var/run /var/.run.save
+ ln -s /run /var/run
+ echo "R /var/.run.save" > /etc/tmpfiles.d/remove-run-save.conf
* when key file cannot be found, read it from kbd in cryptsetup
-* get rid of random file name in generator directory?
- /run/systemd/generator-IH1vFu
-
* add switch to systemctl to show enabled but not running services. Or
another switch that shows service that have been running since
booting but aren't running anymore.
* reuse mkdtemp namespace dirs in /tmp?
-* don't strip facility from kmsg log messages as soon as that is possible:
- http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=9d90c8d9cde929cbc575098e825d7c29d9f45054
-
* recreate systemd's D-Bus private socket file on SIGUSR2
* be more specific what failed:
@@ -105,11 +116,9 @@ Features:
about policy loading. Probably check for available selinux in /proc/filesystems,
and check for active selinux with getcon_raw() == "kernel"
-* optionally create watched directories in .path units
-
* Support --test based on current system state
-* consider services with no [Install] section and stored in /lib enabled by "systemctl is-enabled"
+* systemctl enable as D-Bus call
* consider services with any kind of link in /etc/systemd/system enabled
@@ -120,23 +129,19 @@ Features:
* Maybe implement "systemctl mask" and "systemctl unmask", but not
document it? When doing that add switch to make this temporary by
placing mask links in /dev.
- Consider moving the actual fs operations into systemd behind a D-Bus
- interface, to make namespaces/containers/remote connections work properly.
* detect LXC environment
* invoke vhangup() before and after invoking getty
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=3c95c985fa91ecf6a0e29622bbdd13dcfc5ce9f1
-* support "auto" and "comment=systemd.automount" at the same time for an fstab entry
-
* Maybe store in unit files whether a service should be enabled by default on package installation
(belongs into a distro pattern though, not in an upstream package's service file)
* perhaps add "systemctl reenable" as combination of "systemctl disable" and "systemctl enable"
* need a way to apply mount options of api vfs from systemd unit files
- (or some other modern source?) instead of fstab
+ (or some other modern source?) instead of fstab?
* maybe introduce ExecRestartPre=
@@ -144,12 +149,11 @@ Features:
* Patch systemd-fsck to use -C and pass console fd to it
-* support remote/ssh systemctl/systemadm, and local privileged access → dbus patches need to be merged
-
* configurable jitter for timer events
-* Support ProcessNeededForShutdown=true to allow stuff like mdmon
- to be killed very late after the rootfs is read only (?)
+* Support ProcessNeededForShutdown=true to allow stuff like mdmon to
+ be killed very late after the rootfs is read only? If implement pass
+ this to shutdown binary via command line argument.
* Integrate "mdadm --wait-clean". Maybe just let SIGTERM to mdmon trigger the
needed action
@@ -194,8 +198,6 @@ Features:
* systemctl list-jobs - show dependencies
-* accountsservice is borked
-
* auditd service files
* add systemctl switch to dump transaction without executing it
@@ -208,6 +210,8 @@ Features:
* allow runtime changing of log level and target
+* drop cap bounding set in readahead and other services
+
External:
* udisks should not use udisks-part-id, instead use blkid. also not probe /dev/loopxxx
diff --git a/configure.ac b/configure.ac
index fa8c8ba6d1..730861f78a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@
AC_PREREQ(2.63)
-AC_INIT([systemd],[24],[systemd-devel@lists.freedesktop.org])
+AC_INIT([systemd],[25],[systemd-devel@lists.freedesktop.org])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
@@ -286,6 +286,7 @@ if test "z$with_distro" = "z"; then
test -f "/etc/frugalware-release" && with_distro="frugalware"
test -f "/etc/altlinux-release" && with_distro="altlinux"
test -f "/etc/mandriva-release" && with_distro="mandriva"
+ test -f "/etc/meego-release" && with_distro="meego"
if test "x`lsb_release -is 2>/dev/null`" = "xUbuntu"; then
with_distro="ubuntu"
fi
@@ -360,6 +361,12 @@ case $with_distro in
M4_DISTRO_FLAG=-DTARGET_MANDRIVA=1
have_plymouth=true
;;
+ meego)
+ SYSTEM_SYSVINIT_PATH=
+ SYSTEM_SYSVRCND_PATH=
+ AC_DEFINE(TARGET_MEEGO, [], [Target is MeeGo])
+ M4_DISTRO_FLAG=-DTARGET_MEEGO=1
+ ;;
other)
;;
*)
@@ -409,6 +416,7 @@ AM_CONDITIONAL(TARGET_SLACKWARE, test x"$with_distro" = xslackware)
AM_CONDITIONAL(TARGET_FRUGALWARE, test x"$with_distro" = xfrugalware)
AM_CONDITIONAL(TARGET_ALTLINUX, test x"$with_distro" = xaltlinux)
AM_CONDITIONAL(TARGET_MANDRIVA, test x"$with_distro" = xmandriva)
+AM_CONDITIONAL(TARGET_MEEGO, test x"$with_distro" = xmeego)
AM_CONDITIONAL(HAVE_PLYMOUTH, test -n "$have_plymouth")
AM_CONDITIONAL(HAVE_SYSV_COMPAT, test "$SYSTEM_SYSV_COMPAT" = "yes")
diff --git a/man/daemon.xml b/man/daemon.xml
index ab355cd593..bf454fd040 100644
--- a/man/daemon.xml
+++ b/man/daemon.xml
@@ -869,7 +869,7 @@ fi</programlisting>
a fragment like the following:</para>
<programlisting>%triggerun -- foobar &lt; 0.47.11-1
-if /sbin/chkconfig --level 3 foobar ; then
+if /sbin/chkconfig --level 5 foobar ; then
/bin/systemctl --no-reload enable foobar.service foobar.socket >/dev/null 2>&amp;1 || :
fi</programlisting>
diff --git a/man/hostname.xml b/man/hostname.xml
index f226ef05ad..b8b05c8d35 100644
--- a/man/hostname.xml
+++ b/man/hostname.xml
@@ -44,7 +44,7 @@
<refnamediv>
<refname>hostname</refname>
- <refpurpose>local host name configuration file</refpurpose>
+ <refpurpose>Local host name configuration file</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -62,10 +62,10 @@
newline-terminated host name string. The
host name may be a free-form string up to 64 characters
in length, however it is recommended that it consists
- only of 7bit ASCII characters and no spaces or dots,
- and limit itself to the format allowed for DNS domain
+ only of 7bit ASCII lower-case characters and no spaces or dots,
+ and limits itself to the format allowed for DNS domain
name labels, even though this is not a
- requirement.</para>
+ strict requirement.</para>
<para>Depending on the operating system other
configuration files might be checked for configuration
@@ -85,7 +85,10 @@
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>machine-info</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/machine-id.xml b/man/machine-id.xml
index fefeb66fd6..d0bfbd240d 100644
--- a/man/machine-id.xml
+++ b/man/machine-id.xml
@@ -64,7 +64,7 @@
random source during system installation and stays
constant for all subsequent boots. Optionally, for
stateless systems it is generated during runtime at
- boot.</para>
+ boot if it is found to be empty.</para>
<para>The machine ID does not change based on user
configuration, or when hardware is replaced.</para>
@@ -76,7 +76,7 @@
with a globally unique ID in the network, that does
not change even if the local network configuration
changes. Due to this and its greater length it is
- a more useful replacement than the
+ a more useful replacement for the
<citerefentry><refentrytitle>gethostid</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call POSIX specifies.</para>
</refsect1>
@@ -97,7 +97,9 @@
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>gethostid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>machine-info</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/machine-info.xml b/man/machine-info.xml
new file mode 100644
index 0000000000..c6d3e92f9a
--- /dev/null
+++ b/man/machine-info.xml
@@ -0,0 +1,147 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="machine-info">
+ <refentryinfo>
+ <title>machine-info</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>machine-info</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>machine-info</refname>
+ <refpurpose>Local machine information file</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename>/etc/machine-info</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>The <filename>/etc/machine-info</filename> file
+ contains machine meta data.</para>
+
+ <para>The basic file format of
+ <filename>machine-info</filename> is a
+ newline-separated list of environment-like
+ shell-compatible variable assignments. It is possible
+ to source the configuration from shell scripts,
+ however, beyond mere variable assignments no shell
+ features are supported, allowing applications to read
+ the file without implementing a shell compatible
+ execution engine.</para>
+
+ <para><filename>/etc/machine-info</filename> contains
+ meta data about the machine that is set by the user or
+ administrator.</para>
+
+ <para>Depending on the operating system other
+ configuration files might be checked for machine
+ information as well, however only as fallback.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+
+ <para>The following machine meta data parameters may
+ be set using
+ <filename>/etc/machine-info</filename>:</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><varname>PRETTY_HOSTNAME=</varname></term>
+
+ <listitem><para>A pretty
+ human-readable UTF8 machine identifier
+ string. This should contain a name
+ like <literal>Lennart's
+ Laptop</literal> which is useful to
+ present to the user and does not
+ suffer by the syntax limitations of
+ internet domain names. If possible the
+ internet host name as configured in
+ <filename>/etc/hostname</filename>
+ should be kept similar to this
+ one. Example: if this value is
+ <literal>Lennart's Computer</literal>
+ an Internet host name of
+ <literal>lennarts-computer</literal>
+ might be a good choice. If this
+ parameter is not set an application
+ should fall back to the Internet host
+ name for presentation
+ purposes.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>ICON_NAME=</varname></term>
+
+ <listitem><para>An icon identifying
+ this machine according to the <ulink
+ url="http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html">XDG
+ Icon Naming Specification</ulink>. If
+ this parameter is not set an
+ application should fall back to
+ <literal>computer</literal> or a
+ similar icon name.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Example</title>
+
+ <programlisting>PRETTY_NAME="Lennart's Computer"
+ICON_NAME=computer-laptop</programlisting>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/os-release.xml b/man/os-release.xml
index 759c04d320..d8a45b303f 100644
--- a/man/os-release.xml
+++ b/man/os-release.xml
@@ -165,11 +165,11 @@
</varlistentry>
</variablelist>
- <para>If you interpreting this file from code or a
- shell script, use the ID and VERSION_ID fields. When
- looking for an OS identification string for
- presentation to the user use the PRETTY_STRING
- field.</para>
+ <para>If you are reading this file from code or a
+ shell script to determine the OS or a specific version
+ of it, use the ID and VERSION_ID fields. When looking
+ for an OS identification string for presentation to
+ the user use the PRETTY_NAME field.</para>
<para>Note that operating system vendors may choose
not to provide version information, for example to
@@ -182,10 +182,10 @@
<title>Example</title>
<programlisting>NAME=Fedora
-VERSION=15 (Rawhide)
+VERSION="15 (Rawhide)"
ID=fedora
VERSION_ID=15
-PRETTY_NAME=Fedora 15 (Rawhide)
+PRETTY_NAME="Fedora 15 (Rawhide)"
ANSI_COLOR=0;34</programlisting>
</refsect1>
@@ -193,7 +193,10 @@ ANSI_COLOR=0;34</programlisting>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>lsb_release</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>lsb_release</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>machine-info</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/systemd-ask-password.xml b/man/systemd-ask-password.xml
new file mode 100644
index 0000000000..50aec3403a
--- /dev/null
+++ b/man/systemd-ask-password.xml
@@ -0,0 +1,183 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ This file is part of systemd.
+
+ Copyright 2011 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="systemd-ask-password">
+
+ <refentryinfo>
+ <title>systemd-ask-password</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>systemd-ask-password</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>systemd-ask-password</refname>
+ <refpurpose>Query the user for a system password</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>systemd-ask-password <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="opt">MESSAGE</arg></command>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><command>systemd-ask-password</command> may be
+ used to query a system password or passphrase from the
+ user, using a question message specified on the
+ command line. When run from a TTY it will query a
+ password on the TTY and print it to STDOUT. When run
+ with no TTY or with <option>--no-tty</option> it will
+ query the password system-wide and allow active users
+ to respond via several agents. The latter is
+ only available to privileged processes.</para>
+
+ <para>The purpose of this tool is to query system-wide
+ passwords -- that is passwords not attached to a
+ specific user account. Examples include: unlocking
+ encrypted hard disks when they are plugged in or at
+ boot, entering an SSL certificate passphrase for web
+ and VPN servers.</para>
+
+ <para>Existing agents are: a boot-time password agent
+ asking the user for passwords using Plymouth; a
+ boot-time password agent querying the user directly on
+ the console; an agent requesting password input via a
+ <citerefentry><refentrytitle>wall</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ message; an agent suitable for running in a GNOME
+ session; a command line agent which can be started
+ temporarily to process queued password requests; a TTY
+ agent that is temporarily spawned during
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ invocations.</para>
+
+ <para>Additional password agents may be implemented
+ according to the <ulink
+ url="http://www.freedesktop.org/wiki/Software/systemd/PasswordAgents">systemd
+ Password Agent Specification</ulink>.</para>
+
+ <para>If a password is queried on a tty the user may
+ press TAB to hide the asterisks normally shown for
+ each character typed. Pressing Backspace as first key
+ achieves the same effect.</para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+
+ <para>The following options are understood:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>--h</option></term>
+ <term><option>--help</option></term>
+
+ <listitem><para>Prints a short help
+ text and exits.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--icon=</option></term>
+
+ <listitem><para>Specify an icon name
+ alongside the pasword query, which may
+ be used in all agents supporting
+ graphical display. The icon name
+ should follow the <ulink
+ url="http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html">XDG
+ Icon Naming
+ Specification</ulink>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--timeout=</option></term>
+
+ <listitem><para>Specify the query
+ timeout in seconds. Defaults to
+ 3min.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--no-tty</option></term>
+
+ <listitem><para>Never ask for password
+ on current TTY even if one is
+ available. Always use agent
+ system.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--accept-cached</option></term>
+
+ <listitem><para>If passed accept
+ cached passwords, i.e. passwords
+ previously typed in.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--multiple</option></term>
+
+ <listitem><para>When used in
+ conjunction with
+ <option>--accept-cached</option>
+ accept multiple passwords. This will
+ output one password per
+ line.</para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Exit status</title>
+
+ <para>On success 0 is returned, a non-zero failure
+ code otherwise.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>plymouth</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>wall</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml
index dd66d2ad72..40d236b266 100644
--- a/man/systemd.mount.xml
+++ b/man/systemd.mount.xml
@@ -212,7 +212,7 @@
a time span value such as "5min
20s". Pass 0 to disable the timeout
logic. Defaults to
- 60s.</para></listitem>
+ 3min.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd.path.xml b/man/systemd.path.xml
index d5495c7cc3..e816c3018c 100644
--- a/man/systemd.path.xml
+++ b/man/systemd.path.xml
@@ -168,6 +168,28 @@
identical, except for the
suffix.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>MakeDirectory=</varname></term>
+
+ <listitem><para>Takes a boolean
+ argument. If true the directories to
+ watch are created before
+ watching. This option is ignored for
+ <varname>PathExists=</varname>
+ settings. Defaults to
+ <option>false</option>.</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>DirectoryMode=</varname></term>
+
+ <listitem><para>If
+ <varname>MakeDirectory=</varname> is
+ enabled use the mode specified here to
+ create the directories in
+ question. Takes an access mode in
+ octal notation. Defaults to
+ <option>0755</option>.</para></listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 7458720a3f..335169a397 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -448,7 +448,7 @@
time span value such as "5min
20s". Pass 0 to disable the timeout
logic. Defaults to
- 60s.</para></listitem>
+ 3min.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml
index 8cbb512ec1..d651c14486 100644
--- a/man/systemd.socket.xml
+++ b/man/systemd.socket.xml
@@ -219,6 +219,37 @@
</varlistentry>
<varlistentry>
+ <term><varname>ListenSpecial=</varname></term>
+ <listitem><para>Specifies a special
+ file in the file system to listen
+ on. This expects an absolute file
+ system path as argument. Behaviour
+ otherwise is very similar to the
+ <varname>ListenFIFO=</varname>
+ directive above. Use this to open
+ character device nodes as well as
+ special files in
+ <filename>/proc</filename> and
+ <filename>/sys</filename>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>ListenNetlink=</varname></term>
+ <listitem><para>Specifies a Netlink
+ family to create a socket for to
+ listen on. This expects a short string
+ referring to the AF_NETLINK family
+ name (such as <varname>audit</varname>
+ or <varname>kobject-uevent</varname>)
+ as argument, optionally suffixed by a
+ whitespace followed by a multicast
+ group integer. Behaviour otherwise is
+ very similar to the
+ <varname>ListenDatagram=</varname>
+ directive above.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>BindIPv6Only=</varname></term>
<listitem><para>Takes a one of
<option>default</option>,
@@ -510,7 +541,7 @@
a time span value such as "5min
20s". Pass 0 to disable the timeout
logic. Defaults to
- 60s.</para></listitem>
+ 3min.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 5460ebeb2f..65a76be3b7 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -445,6 +445,32 @@
</varlistentry>
<varlistentry>
+ <term><varname>OnFailureIsolate=</varname></term>
+
+ <listitem><para>Takes a boolean
+ argument. If <option>true</option> the
+ unit listed in
+ <varname>OnFailure=</varname> will be
+ enqueued in isolation mode, i.e. all
+ units that are not its dependency will
+ be stopped. If this is set only a
+ single unit may be listed in
+ <varname>OnFailure=</varname>. Defaults
+ to
+ <option>false</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>IgnoreOnIsolate=</varname></term>
+
+ <listitem><para>Takes a boolean
+ argument. If <option>true</option>
+ this unit will not be stopped when
+ isolating another unit. Defaults to
+ <option>false</option>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>StopWhenUnneeded=</varname></term>
<listitem><para>Takes a boolean
diff --git a/src/ask-password-api.c b/src/ask-password-api.c
index da967ab7a1..04d5623d9e 100644
--- a/src/ask-password-api.c
+++ b/src/ask-password-api.c
@@ -404,13 +404,13 @@ int ask_password_agent(
t = now(CLOCK_MONOTONIC);
- if (until <= t) {
+ if (until > 0 && until <= t) {
log_notice("Timed out");
r = -ETIME;
goto finish;
}
- if ((k = poll(pollfd, _FD_MAX, (until-t)/USEC_PER_MSEC)) < 0) {
+ if ((k = poll(pollfd, _FD_MAX, until > 0 ? (int) ((until-t)/USEC_PER_MSEC) : -1)) < 0) {
if (errno == EINTR)
continue;
@@ -481,7 +481,13 @@ int ask_password_agent(
if (passphrase[0] == '+') {
char **l;
- if (!(l = strv_parse_nulstr(passphrase+1, n-1))) {
+ if (n == 1)
+ l = strv_new("", NULL);
+ else
+ l = strv_parse_nulstr(passphrase+1, n-1);
+ /* An empty message refers to the empty password */
+
+ if (!l) {
r = -ENOMEM;
goto finish;
}
diff --git a/src/ask-password.c b/src/ask-password.c
index c77376482e..5162f62eee 100644
--- a/src/ask-password.c
+++ b/src/ask-password.c
@@ -40,11 +40,12 @@
#include "util.h"
#include "strv.h"
#include "ask-password-api.h"
+#include "def.h"
static const char *arg_icon = NULL;
static const char *arg_message = NULL;
static bool arg_use_tty = true;
-static usec_t arg_timeout = 60 * USEC_PER_SEC;
+static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
static bool arg_accept_cached = false;
static bool arg_multiple = false;
@@ -101,7 +102,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_TIMEOUT:
- if (parse_usec(optarg, &arg_timeout) < 0 || arg_timeout <= 0) {
+ if (parse_usec(optarg, &arg_timeout) < 0) {
log_error("Failed to parse --timeout parameter %s", optarg);
return -EINVAL;
}
@@ -139,6 +140,7 @@ static int parse_argv(int argc, char *argv[]) {
int main(int argc, char *argv[]) {
int r;
+ usec_t timeout;
log_parse_environment();
log_open();
@@ -146,10 +148,15 @@ int main(int argc, char *argv[]) {
if ((r = parse_argv(argc, argv)) <= 0)
goto finish;
+ if (arg_timeout > 0)
+ timeout = now(CLOCK_MONOTONIC) + arg_timeout;
+ else
+ timeout = 0;
+
if (arg_use_tty && isatty(STDIN_FILENO)) {
char *password = NULL;
- if ((r = ask_password_tty(arg_message, now(CLOCK_MONOTONIC) + arg_timeout, NULL, &password)) >= 0) {
+ if ((r = ask_password_tty(arg_message, timeout, NULL, &password)) >= 0) {
puts(password);
free(password);
}
@@ -157,7 +164,7 @@ int main(int argc, char *argv[]) {
} else {
char **l;
- if ((r = ask_password_agent(arg_message, arg_icon, now(CLOCK_MONOTONIC) + arg_timeout, arg_accept_cached, &l)) >= 0) {
+ if ((r = ask_password_agent(arg_message, arg_icon, timeout, arg_accept_cached, &l)) >= 0) {
char **p;
STRV_FOREACH(p, l) {
diff --git a/src/automount.c b/src/automount.c
index f6f83d43b6..33c962e0c0 100644
--- a/src/automount.c
+++ b/src/automount.c
@@ -58,6 +58,8 @@ static void automount_init(Unit *u) {
a->pipe_watch.type = WATCH_INVALID;
a->directory_mode = 0755;
+
+ a->meta.ignore_on_isolate = true;
}
static void repeat_unmout(const char *path) {
diff --git a/src/cgroup.c b/src/cgroup.c
index 5864858dd7..0c6f20d4b7 100644
--- a/src/cgroup.c
+++ b/src/cgroup.c
@@ -63,7 +63,7 @@ int cgroup_bonding_realize_list(CGroupBonding *first) {
return 0;
}
-void cgroup_bonding_free(CGroupBonding *b) {
+void cgroup_bonding_free(CGroupBonding *b, bool remove_or_trim) {
assert(b);
if (b->unit) {
@@ -82,7 +82,7 @@ void cgroup_bonding_free(CGroupBonding *b) {
}
}
- if (b->realized && b->ours) {
+ if (b->realized && b->ours && remove_or_trim) {
if (cgroup_bonding_is_empty(b) > 0)
cg_delete(b->controller, b->path);
@@ -95,11 +95,11 @@ void cgroup_bonding_free(CGroupBonding *b) {
free(b);
}
-void cgroup_bonding_free_list(CGroupBonding *first) {
+void cgroup_bonding_free_list(CGroupBonding *first, bool remove_or_trim) {
CGroupBonding *b, *n;
LIST_FOREACH_SAFE(by_unit, b, n, first)
- cgroup_bonding_free(b);
+ cgroup_bonding_free(b, remove_or_trim);
}
void cgroup_bonding_trim(CGroupBonding *b, bool delete_root) {
@@ -225,6 +225,12 @@ int manager_setup_cgroup(Manager *m) {
assert(m);
+ /* 0. Be nice to Ingo Molnar #628004 */
+ if (path_is_mount_point("/sys/fs/cgroup/systemd") <= 0) {
+ log_warning("No control group support available, not creating root group.");
+ return 0;
+ }
+
/* 1. Determine hierarchy */
if ((r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 0, &current)) < 0) {
log_error("Cannot determine cgroup we are running in: %s", strerror(-r));
diff --git a/src/cgroup.h b/src/cgroup.h
index a6ac90fb09..c6dff4313e 100644
--- a/src/cgroup.h
+++ b/src/cgroup.h
@@ -53,8 +53,8 @@ struct CGroupBonding {
int cgroup_bonding_realize(CGroupBonding *b);
int cgroup_bonding_realize_list(CGroupBonding *first);
-void cgroup_bonding_free(CGroupBonding *b);
-void cgroup_bonding_free_list(CGroupBonding *first);
+void cgroup_bonding_free(CGroupBonding *b, bool remove_or_trim);
+void cgroup_bonding_free_list(CGroupBonding *first, bool remove_or_trim);
int cgroup_bonding_install(CGroupBonding *b, pid_t pid);
int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid);
diff --git a/src/cgroups-agent.c b/src/cgroups-agent.c
index e0868b6137..7f001e67d1 100644
--- a/src/cgroups-agent.c
+++ b/src/cgroups-agent.c
@@ -43,7 +43,6 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
-
/* We send this event to the private D-Bus socket and then the
* system instance will forward this to the system bus. We do
* this to avoid an activation loop when we start dbus when we
@@ -94,7 +93,6 @@ finish:
dbus_connection_unref(bus);
}
-
if (m)
dbus_message_unref(m);
diff --git a/src/cryptsetup-generator.c b/src/cryptsetup-generator.c
index 00f48009ed..696f44ae36 100644
--- a/src/cryptsetup-generator.c
+++ b/src/cryptsetup-generator.c
@@ -33,6 +33,11 @@ static bool has_option(const char *haystack, const char *needle) {
const char *f = haystack;
size_t l;
+ assert(needle);
+
+ if (!haystack)
+ return false;
+
l = strlen(needle);
while ((f = strstr(f, needle))) {
@@ -62,10 +67,14 @@ static int create_disk(
char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *from = NULL, *to = NULL, *e = NULL;
int r;
FILE *f = NULL;
+ bool noauto, nofail;
assert(name);
assert(device);
+ noauto = has_option(options, "noauto");
+ nofail = has_option(options, "nofail");
+
if (!(n = unit_name_build_escape("cryptsetup", name, ".service"))) {
r = -ENOMEM;
log_error("Failed to allocate unit name.");
@@ -99,12 +108,17 @@ static int create_disk(
fprintf(f,
"[Unit]\n"
"Description=Cryptography Setup for %%I\n"
+ "Conflicts=umount.target\n"
"DefaultDependencies=no\n"
"BindTo=%s dev-mapper-%%i.device\n"
"After=systemd-readahead-collect.service systemd-readahead-replay.service %s\n"
- "Before=dev-mapper-%%i.device shutdown.target cryptsetup.target\n",
+ "Before=umount.target\n",
d, d);
+ if (!nofail)
+ fprintf(f,
+ "Before=cryptsetup.target\n");
+
if (password && (streq(password, "/dev/urandom") ||
streq(password, "/dev/random") ||
streq(password, "/dev/hw_random")))
@@ -115,19 +129,20 @@ static int create_disk(
"\n[Service]\n"
"Type=oneshot\n"
"RemainAfterExit=yes\n"
+ "TimeoutSec=0\n" /* the binary handles timeouts anyway */
"ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n"
"ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
name, u, strempty(password), strempty(options),
name);
- if (options && has_option(options, "tmp"))
+ if (has_option(options, "tmp"))
fprintf(f,
- "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'",
+ "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n",
name);
- if (options && has_option(options, "swap"))
+ if (has_option(options, "swap"))
fprintf(f,
- "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'",
+ "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n",
name);
fflush(f);
@@ -143,7 +158,7 @@ static int create_disk(
goto fail;
}
- if (!options || !has_option(options, "noauto")) {
+ if (!noauto) {
if (asprintf(&to, "%s/%s.wants/%s", arg_dest, d, n) < 0) {
r = -ENOMEM;
@@ -161,20 +176,22 @@ static int create_disk(
free(to);
to = NULL;
- if (!options || !has_option(options, "nofail")) {
+ if (!nofail)
+ asprintf(&to, "%s/cryptsetup.target.requires/%s", arg_dest, n);
+ else
+ asprintf(&to, "%s/cryptsetup.target.wants/%s", arg_dest, n);
- if (asprintf(&to, "%s/cryptsetup.target.wants/%s", arg_dest, n) < 0) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!to) {
+ r = -ENOMEM;
+ goto fail;
+ }
- mkdir_parents(to, 0755);
+ mkdir_parents(to, 0755);
- if (symlink(from, to) < 0) {
- log_error("Failed to create symlink '%s' to '%s': %m", from, to);
- r = -errno;
- goto fail;
- }
+ if (symlink(from, to) < 0) {
+ log_error("Failed to create symlink '%s' to '%s': %m", from, to);
+ r = -errno;
+ goto fail;
}
}
diff --git a/src/cryptsetup.c b/src/cryptsetup.c
index 3aa822a1d0..4ef9606d39 100644
--- a/src/cryptsetup.c
+++ b/src/cryptsetup.c
@@ -40,7 +40,7 @@ static char *opt_hash = NULL;
static unsigned opt_tries = 0;
static bool opt_readonly = false;
static bool opt_verify = false;
-static usec_t opt_timeout = 0;
+static usec_t opt_timeout = DEFAULT_TIMEOUT_USEC;
/* Options Debian's crypttab knows we don't:
@@ -309,7 +309,10 @@ int main(int argc, char *argv[]) {
if (opt_readonly)
flags |= CRYPT_ACTIVATE_READONLY;
- until = now(CLOCK_MONOTONIC) + (opt_timeout > 0 ? opt_timeout : DEFAULT_TIMEOUT_USEC);
+ if (opt_timeout > 0)
+ until = now(CLOCK_MONOTONIC) + opt_timeout;
+ else
+ until = 0;
opt_tries = opt_tries > 0 ? opt_tries : 3;
opt_key_size = (opt_key_size > 0 ? opt_key_size : 256);
@@ -404,6 +407,8 @@ int main(int argc, char *argv[]) {
}
}
+ k = 0;
+
if (!opt_type || streq(opt_type, CRYPT_LUKS1))
k = crypt_load(cd, CRYPT_LUKS1, NULL);
diff --git a/src/dbus-automount.c b/src/dbus-automount.c
index eccad37e8b..826842560d 100644
--- a/src/dbus-automount.c
+++ b/src/dbus-automount.c
@@ -21,6 +21,7 @@
#include "dbus-unit.h"
#include "dbus-automount.h"
+#include "dbus-common.h"
#define BUS_AUTOMOUNT_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Automount\">\n" \
@@ -52,5 +53,5 @@ DBusHandlerResult bus_automount_message_handler(Unit *u, DBusConnection *c, DBus
{ NULL, NULL, NULL, NULL, NULL }
};
- return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
+ return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, properties);
}
diff --git a/src/dbus-common.c b/src/dbus-common.c
index dcce10e552..b23373c5d1 100644
--- a/src/dbus-common.c
+++ b/src/dbus-common.c
@@ -26,11 +26,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <dbus/dbus.h>
+#include <string.h>
#include "log.h"
#include "dbus-common.h"
#include "util.h"
#include "def.h"
+#include "strv.h"
int bus_check_peercred(DBusConnection *c) {
int fd;
@@ -232,3 +234,448 @@ const char *bus_error_message(const DBusError *error) {
return error->message;
}
+
+DBusHandlerResult bus_default_message_handler(
+ DBusConnection *c,
+ DBusMessage *message,
+ const char *introspection,
+ const char *interfaces,
+ const BusProperty *properties) {
+
+ DBusError error;
+ DBusMessage *reply = NULL;
+ int r;
+
+ assert(c);
+ assert(message);
+
+ dbus_error_init(&error);
+
+ if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect") && introspection) {
+
+ if (!(reply = dbus_message_new_method_return(message)))
+ goto oom;
+
+ if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID))
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Get") && properties) {
+ const char *interface, *property;
+ const BusProperty *p;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(c, message, &error, -EINVAL);
+
+ for (p = properties; p->property; p++)
+ if (streq(p->interface, interface) && streq(p->property, property))
+ break;
+
+ if (p->property) {
+ DBusMessageIter iter, sub;
+
+ if (!(reply = dbus_message_new_method_return(message)))
+ goto oom;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, p->signature, &sub))
+ goto oom;
+
+ if ((r = p->append(&sub, property, (void*) p->data)) < 0) {
+
+ if (r == -ENOMEM)
+ goto oom;
+
+ dbus_message_unref(reply);
+ return bus_send_error_reply(c, message, NULL, r);
+ }
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ goto oom;
+ } else {
+ if (!nulstr_contains(interfaces, interface))
+ dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
+ else
+ dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
+
+ return bus_send_error_reply(c, message, &error, -EINVAL);
+ }
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "GetAll") && properties) {
+ const char *interface;
+ const BusProperty *p;
+ DBusMessageIter iter, sub, sub2, sub3;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(c, message, &error, -EINVAL);
+
+ if (interface[0] && !nulstr_contains(interfaces, interface)) {
+ dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
+ return bus_send_error_reply(c, message, &error, -EINVAL);
+ }
+
+ if (!(reply = dbus_message_new_method_return(message)))
+ goto oom;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub))
+ goto oom;
+
+ for (p = properties; p->property; p++) {
+ if (interface[0] && !streq(p->interface, interface))
+ continue;
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &p->property) ||
+ !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, p->signature, &sub3))
+ goto oom;
+
+ if ((r = p->append(&sub3, p->property, (void*) p->data)) < 0) {
+
+ if (r == -ENOMEM)
+ goto oom;
+
+ dbus_message_unref(reply);
+ return bus_send_error_reply(c, message, NULL, r);
+ }
+
+ if (!dbus_message_iter_close_container(&sub2, &sub3) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ goto oom;
+ }
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && properties) {
+ const char *interface, *property;
+ DBusMessageIter iter;
+ const BusProperty *p;
+
+ if (!dbus_message_iter_init(message, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return bus_send_error_reply(c, message, NULL, -EINVAL);
+
+ dbus_message_iter_get_basic(&iter, &interface);
+
+ if (!dbus_message_iter_next(&iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return bus_send_error_reply(c, message, NULL, -EINVAL);
+
+ dbus_message_iter_get_basic(&iter, &property);
+
+ if (!dbus_message_iter_next(&iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT ||
+ dbus_message_iter_has_next(&iter))
+ return bus_send_error_reply(c, message, NULL, -EINVAL);
+
+ for (p = properties; p->property; p++)
+ if (streq(p->interface, interface) && streq(p->property, property))
+ break;
+
+ if (p->set) {
+ DBusMessageIter sub;
+ char *sig;
+
+ dbus_message_iter_recurse(&iter, &sub);
+
+ if (!(sig = dbus_message_iter_get_signature(&sub)))
+ goto oom;
+
+ if (!streq(sig, p->signature)) {
+ dbus_free(sig);
+ return bus_send_error_reply(c, message, NULL, -EINVAL);
+ }
+
+ dbus_free(sig);
+
+ if ((r = p->set(&sub, property)) < 0) {
+ if (r == -ENOMEM)
+ goto oom;
+ return bus_send_error_reply(c, message, NULL, r);
+ }
+
+ if (!(reply = dbus_message_new_method_return(message)))
+ goto oom;
+ } else {
+ if (p->property)
+ dbus_set_error_const(&error, DBUS_ERROR_PROPERTY_READ_ONLY, "Property read-only");
+ else if (!nulstr_contains(interfaces, interface))
+ dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
+ else
+ dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
+
+ return bus_send_error_reply(c, message, &error, -EINVAL);
+ }
+
+ } else if (!nulstr_contains(interfaces, dbus_message_get_interface(message))) {
+ dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
+ return bus_send_error_reply(c, message, &error, -EINVAL);
+ }
+
+ if (reply) {
+ if (!dbus_connection_send(c, reply, NULL))
+ goto oom;
+
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+oom:
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+}
+
+int bus_property_append_string(DBusMessageIter *i, const char *property, void *data) {
+ const char *t = data;
+
+ assert(i);
+ assert(property);
+
+ if (!t)
+ t = "";
+
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
+ return -ENOMEM;
+
+ return 0;
+}
+
+int bus_property_append_strv(DBusMessageIter *i, const char *property, void *data) {
+ DBusMessageIter sub;
+ char **t = data;
+
+ assert(i);
+ assert(property);
+
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
+ return -ENOMEM;
+
+ STRV_FOREACH(t, t)
+ if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, t))
+ return -ENOMEM;
+
+ if (!dbus_message_iter_close_container(i, &sub))
+ return -ENOMEM;
+
+ return 0;
+}
+
+int bus_property_append_bool(DBusMessageIter *i, const char *property, void *data) {
+ bool *b = data;
+ dbus_bool_t db;
+
+ assert(i);
+ assert(property);
+ assert(b);
+
+ db = *b;
+
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
+ return -ENOMEM;
+
+ return 0;
+}
+
+int bus_property_append_uint64(DBusMessageIter *i, const char *property, void *data) {
+ assert(i);
+ assert(property);
+ assert(data);
+
+ /* Let's ensure that pid_t is actually 64bit, and hence this
+ * function can be used for usec_t */
+ assert_cc(sizeof(uint64_t) == sizeof(usec_t));
+
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, data))
+ return -ENOMEM;
+
+ return 0;
+}
+
+int bus_property_append_uint32(DBusMessageIter *i, const char *property, void *data) {
+ assert(i);
+ assert(property);
+ assert(data);
+
+ /* Let's ensure that pid_t and mode_t is actually 32bit, and
+ * hence this function can be used for pid_t/mode_t */
+ assert_cc(sizeof(uint32_t) == sizeof(pid_t));
+ assert_cc(sizeof(uint32_t) == sizeof(mode_t));
+ assert_cc(sizeof(uint32_t) == sizeof(unsigned));
+
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, data))
+ return -ENOMEM;
+
+ return 0;
+}
+
+int bus_property_append_int32(DBusMessageIter *i, const char *property, void *data) {
+ assert(i);
+ assert(property);
+ assert(data);
+
+ assert_cc(sizeof(int32_t) == sizeof(int));
+
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, data))
+ return -ENOMEM;
+
+ return 0;
+}
+
+int bus_property_append_size(DBusMessageIter *i, const char *property, void *data) {
+ uint64_t u;
+
+ assert(i);
+ assert(property);
+ assert(data);
+
+ u = (uint64_t) *(size_t*) data;
+
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
+ return -ENOMEM;
+
+ return 0;
+}
+
+int bus_property_append_ul(DBusMessageIter *i, const char *property, void *data) {
+ uint64_t u;
+
+ assert(i);
+ assert(property);
+ assert(data);
+
+ u = (uint64_t) *(unsigned long*) data;
+
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
+ return -ENOMEM;
+
+ return 0;
+}
+
+const char *bus_errno_to_dbus(int error) {
+
+ switch(error) {
+
+ case -EINVAL:
+ return DBUS_ERROR_INVALID_ARGS;
+
+ case -ENOMEM:
+ return DBUS_ERROR_NO_MEMORY;
+
+ case -EPERM:
+ case -EACCES:
+ return DBUS_ERROR_ACCESS_DENIED;
+
+ case -ESRCH:
+ return DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN;
+
+ case -ENOENT:
+ return DBUS_ERROR_FILE_NOT_FOUND;
+
+ case -EEXIST:
+ return DBUS_ERROR_FILE_EXISTS;
+
+ case -ETIMEDOUT:
+ case -ETIME:
+ return DBUS_ERROR_TIMEOUT;
+
+ case -EIO:
+ return DBUS_ERROR_IO_ERROR;
+
+ case -ENETRESET:
+ case -ECONNABORTED:
+ case -ECONNRESET:
+ return DBUS_ERROR_DISCONNECTED;
+ }
+
+ return DBUS_ERROR_FAILED;
+}
+
+DBusHandlerResult bus_send_error_reply(DBusConnection *c, DBusMessage *message, DBusError *berror, int error) {
+ DBusMessage *reply = NULL;
+ const char *name, *text;
+
+ if (berror && dbus_error_is_set(berror)) {
+ name = berror->name;
+ text = berror->message;
+ } else {
+ name = bus_errno_to_dbus(error);
+ text = strerror(-error);
+ }
+
+ if (!(reply = dbus_message_new_error(message, name, text)))
+ goto oom;
+
+ if (!dbus_connection_send(c, reply, NULL))
+ goto oom;
+
+ dbus_message_unref(reply);
+
+ if (berror)
+ dbus_error_free(berror);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+
+oom:
+ if (reply)
+ dbus_message_unref(reply);
+
+ if (berror)
+ dbus_error_free(berror);
+
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+}
+
+DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties) {
+ DBusMessage *m;
+ DBusMessageIter iter, sub;
+ const char *i;
+
+ assert(interface);
+ assert(properties);
+
+ if (!(m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged")))
+ goto oom;
+
+ dbus_message_iter_init_append(m, &iter);
+
+ /* We won't send any property values, since they might be
+ * large and sometimes not cheap to generated */
+
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
+ !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
+ !dbus_message_iter_close_container(&iter, &sub) ||
+ !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
+ goto oom;
+
+ NULSTR_FOREACH(i, properties)
+ if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &i))
+ goto oom;
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ goto oom;
+
+ return m;
+
+oom:
+ if (m)
+ dbus_message_unref(m);
+
+ return NULL;
+}
diff --git a/src/dbus-common.h b/src/dbus-common.h
index 76333cd4f6..729519c526 100644
--- a/src/dbus-common.h
+++ b/src/dbus-common.h
@@ -24,6 +24,65 @@
#include <dbus/dbus.h>
+#ifndef DBUS_ERROR_UNKNOWN_OBJECT
+#define DBUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject"
+#endif
+
+#ifndef DBUS_ERROR_UNKNOWN_INTERFACE
+#define DBUS_ERROR_UNKNOWN_INTERFACE "org.freedesktop.DBus.Error.UnknownInterface"
+#endif
+
+#ifndef DBUS_ERROR_UNKNOWN_PROPERTY
+#define DBUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty"
+#endif
+
+#ifndef DBUS_ERROR_PROPERTY_READ_ONLY
+#define DBUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly"
+#endif
+
+#define BUS_PROPERTIES_INTERFACE \
+ " <interface name=\"org.freedesktop.DBus.Properties\">\n" \
+ " <method name=\"Get\">\n" \
+ " <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
+ " <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
+ " <arg name=\"value\" direction=\"out\" type=\"v\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetAll\">\n" \
+ " <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
+ " <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n" \
+ " </method>\n" \
+ " <method name=\"Set\">\n" \
+ " <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
+ " <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
+ " <arg name=\"value\" direction=\"in\" type=\"v\"/>\n" \
+ " </method>\n" \
+ " <signal name=\"PropertiesChanged\">\n" \
+ " <arg type=\"s\" name=\"interface\"/>\n" \
+ " <arg type=\"a{sv}\" name=\"changed_properties\"/>\n" \
+ " <arg type=\"as\" name=\"invalidated_properties\"/>\n" \
+ " </signal>\n" \
+ " </interface>\n"
+
+#define BUS_INTROSPECTABLE_INTERFACE \
+ " <interface name=\"org.freedesktop.DBus.Introspectable\">\n" \
+ " <method name=\"Introspect\">\n" \
+ " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " </interface>\n"
+
+#define BUS_PEER_INTERFACE \
+ "<interface name=\"org.freedesktop.DBus.Peer\">\n" \
+ " <method name=\"Ping\"/>\n" \
+ " <method name=\"GetMachineId\">\n" \
+ " <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ "</interface>\n"
+
+#define BUS_GENERIC_INTERFACES_LIST \
+ "org.freedesktop.DBus.Properties\0" \
+ "org.freedesktop.DBus.Introspectable\0" \
+ "org.freedesktop.DBus.Peer\0"
+
int bus_check_peercred(DBusConnection *c);
int bus_connect(DBusBusType t, DBusConnection **_bus, bool *private_bus, DBusError *error);
@@ -33,4 +92,64 @@ int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error);
const char *bus_error_message(const DBusError *error);
+typedef int (*BusPropertyCallback)(DBusMessageIter *iter, const char *property, void *data);
+typedef int (*BusPropertySetCallback)(DBusMessageIter *iter, const char *property);
+
+typedef struct BusProperty {
+ const char *interface; /* interface of the property */
+ const char *property; /* name of the property */
+ BusPropertyCallback append; /* Function that is called to serialize this property */
+ const char *signature;
+ const void *data; /* The data of this property */
+ BusPropertySetCallback set; /* Optional: Function that is called to set this property */
+} BusProperty;
+
+DBusHandlerResult bus_send_error_reply(
+ DBusConnection *c,
+ DBusMessage *message,
+ DBusError *bus_error,
+ int error);
+
+DBusHandlerResult bus_default_message_handler(
+ DBusConnection *c,
+ DBusMessage *message,
+ const char *introspection,
+ const char *interfaces,
+ const BusProperty *properties);
+
+int bus_property_append_string(DBusMessageIter *i, const char *property, void *data);
+int bus_property_append_strv(DBusMessageIter *i, const char *property, void *data);
+int bus_property_append_bool(DBusMessageIter *i, const char *property, void *data);
+int bus_property_append_int32(DBusMessageIter *i, const char *property, void *data);
+int bus_property_append_uint32(DBusMessageIter *i, const char *property, void *data);
+int bus_property_append_uint64(DBusMessageIter *i, const char *property, void *data);
+int bus_property_append_size(DBusMessageIter *i, const char *property, void *data);
+int bus_property_append_ul(DBusMessageIter *i, const char *property, void *data);
+
+#define bus_property_append_int bus_property_append_int32
+#define bus_property_append_pid bus_property_append_uint32
+#define bus_property_append_mode bus_property_append_uint32
+#define bus_property_append_unsigned bus_property_append_uint32
+#define bus_property_append_usec bus_property_append_uint64
+
+#define DEFINE_BUS_PROPERTY_APPEND_ENUM(function,name,type) \
+ int function(DBusMessageIter *i, const char *property, void *data) { \
+ const char *value; \
+ type *field = data; \
+ \
+ assert(i); \
+ assert(property); \
+ \
+ value = name##_to_string(*field); \
+ \
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &value)) \
+ return -ENOMEM; \
+ \
+ return 0; \
+ }
+
+const char *bus_errno_to_dbus(int error);
+
+DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties);
+
#endif
diff --git a/src/dbus-device.c b/src/dbus-device.c
index b046eae9f7..f85ad2daf8 100644
--- a/src/dbus-device.c
+++ b/src/dbus-device.c
@@ -21,6 +21,7 @@
#include "dbus-unit.h"
#include "dbus-device.h"
+#include "dbus-common.h"
#define BUS_DEVICE_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Device\">\n" \
@@ -53,5 +54,5 @@ DBusHandlerResult bus_device_message_handler(Unit *u, DBusConnection *c, DBusMes
{ NULL, NULL, NULL, NULL, NULL }
};
- return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
+ return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, properties);
}
diff --git a/src/dbus-execute.c b/src/dbus-execute.c
index 35e6d377ee..3f8fafe6cd 100644
--- a/src/dbus-execute.c
+++ b/src/dbus-execute.c
@@ -27,17 +27,17 @@
#include "missing.h"
#include "ioprio.h"
#include "strv.h"
+#include "dbus-common.h"
DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_kill_mode, kill_mode, KillMode);
DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
-int bus_execute_append_env_files(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
char **env_files = data, **j;
DBusMessageIter sub, sub2;
- assert(m);
assert(i);
assert(property);
@@ -66,11 +66,10 @@ int bus_execute_append_env_files(Manager *m, DBusMessageIter *i, const char *pro
return 0;
}
-int bus_execute_append_oom_score_adjust(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
int32_t n;
- assert(m);
assert(i);
assert(property);
assert(c);
@@ -101,11 +100,10 @@ int bus_execute_append_oom_score_adjust(Manager *m, DBusMessageIter *i, const ch
return 0;
}
-int bus_execute_append_nice(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
int32_t n;
- assert(m);
assert(i);
assert(property);
assert(c);
@@ -121,11 +119,10 @@ int bus_execute_append_nice(Manager *m, DBusMessageIter *i, const char *property
return 0;
}
-int bus_execute_append_ioprio(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
int32_t n;
- assert(m);
assert(i);
assert(property);
assert(c);
@@ -141,11 +138,10 @@ int bus_execute_append_ioprio(Manager *m, DBusMessageIter *i, const char *proper
return 0;
}
-int bus_execute_append_cpu_sched_policy(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
int32_t n;
- assert(m);
assert(i);
assert(property);
assert(c);
@@ -161,11 +157,10 @@ int bus_execute_append_cpu_sched_policy(Manager *m, DBusMessageIter *i, const ch
return 0;
}
-int bus_execute_append_cpu_sched_priority(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
int32_t n;
- assert(m);
assert(i);
assert(property);
assert(c);
@@ -187,12 +182,11 @@ int bus_execute_append_cpu_sched_priority(Manager *m, DBusMessageIter *i, const
return 0;
}
-int bus_execute_append_affinity(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
dbus_bool_t b;
DBusMessageIter sub;
- assert(m);
assert(i);
assert(property);
assert(c);
@@ -214,11 +208,10 @@ int bus_execute_append_affinity(Manager *m, DBusMessageIter *i, const char *prop
return 0;
}
-int bus_execute_append_timer_slack_nsec(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
uint64_t u;
- assert(m);
assert(i);
assert(property);
assert(c);
@@ -234,11 +227,10 @@ int bus_execute_append_timer_slack_nsec(Manager *m, DBusMessageIter *i, const ch
return 0;
}
-int bus_execute_append_capability_bs(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
uint64_t normal, inverted;
- assert(m);
assert(i);
assert(property);
assert(c);
@@ -249,16 +241,15 @@ int bus_execute_append_capability_bs(Manager *m, DBusMessageIter *i, const char
normal = *(uint64_t*) data;
inverted = ~normal;
- return bus_property_append_uint64(m, i, property, &inverted);
+ return bus_property_append_uint64(i, property, &inverted);
}
-int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
char *t = NULL;
const char *s;
dbus_bool_t b;
- assert(m);
assert(i);
assert(property);
assert(c);
@@ -282,12 +273,11 @@ int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *
return 0;
}
-int bus_execute_append_rlimits(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
int r;
uint64_t u;
- assert(m);
assert(i);
assert(property);
assert(c);
@@ -311,11 +301,10 @@ int bus_execute_append_rlimits(Manager *m, DBusMessageIter *i, const char *prope
return 0;
}
-int bus_execute_append_command(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_execute_append_command(DBusMessageIter *i, const char *property, void *data) {
ExecCommand *c = data;
DBusMessageIter sub, sub2, sub3;
- assert(m);
assert(i);
assert(property);
@@ -346,7 +335,9 @@ int bus_execute_append_command(Manager *m, DBusMessageIter *i, const char *prope
if (!dbus_message_iter_close_container(&sub2, &sub3) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &c->ignore) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.monotonic) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.monotonic) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &code) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &status))
diff --git a/src/dbus-execute.h b/src/dbus-execute.h
index 8bfaaaf120..ed66390d0b 100644
--- a/src/dbus-execute.h
+++ b/src/dbus-execute.h
@@ -28,7 +28,9 @@
#define BUS_EXEC_STATUS_INTERFACE(prefix) \
" <property name=\"" prefix "StartTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"" prefix "StartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"" prefix "ExitTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"" prefix "ExitTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"" prefix "PID\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"" prefix "Code\" type=\"i\" access=\"read\"/>\n" \
" <property name=\"" prefix "Status\" type=\"i\" access=\"read\"/>\n"
@@ -149,28 +151,30 @@
#define BUS_EXEC_STATUS_PROPERTIES(interface, estatus, prefix) \
{ interface, prefix "StartTimestamp", bus_property_append_usec, "t", &(estatus).start_timestamp.realtime }, \
+ { interface, prefix "StartTimestampMonotonic",bus_property_append_usec, "t", &(estatus).start_timestamp.monotonic }, \
{ interface, prefix "ExitTimestamp", bus_property_append_usec, "t", &(estatus).start_timestamp.realtime }, \
+ { interface, prefix "ExitTimestampMonotonic", bus_property_append_usec, "t", &(estatus).start_timestamp.monotonic }, \
{ interface, prefix "PID", bus_property_append_pid, "u", &(estatus).pid }, \
{ interface, prefix "Code", bus_property_append_int, "i", &(estatus).code }, \
{ interface, prefix "Status", bus_property_append_int, "i", &(estatus).status }
#define BUS_EXEC_COMMAND_PROPERTY(interface, command, name) \
- { interface, name, bus_execute_append_command, "a(sasbttuii)", (command) }
-
-int bus_execute_append_output(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_input(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_oom_score_adjust(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_nice(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_ioprio(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_cpu_sched_policy(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_cpu_sched_priority(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_affinity(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_timer_slack_nsec(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_capability_bs(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_rlimits(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_command(Manager *m, DBusMessageIter *u, const char *property, void *data);
-int bus_execute_append_kill_mode(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_execute_append_env_files(Manager *m, DBusMessageIter *i, const char *property, void *data);
+ { interface, name, bus_execute_append_command, "a(sasbttttuii)", (command) }
+
+int bus_execute_append_output(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_input(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_command(DBusMessageIter *u, const char *property, void *data);
+int bus_execute_append_kill_mode(DBusMessageIter *i, const char *property, void *data);
+int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data);
#endif
diff --git a/src/dbus-job.c b/src/dbus-job.c
index 908ddba537..2308be34fd 100644
--- a/src/dbus-job.c
+++ b/src/dbus-job.c
@@ -24,6 +24,7 @@
#include "dbus.h"
#include "log.h"
#include "dbus-job.h"
+#include "dbus-common.h"
#define BUS_JOB_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Job\">\n" \
@@ -55,12 +56,11 @@ const char bus_job_interface[] _introspect_("Job") = BUS_JOB_INTERFACE;
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_state, job_state, JobState);
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_type, job_type, JobType);
-static int bus_job_append_unit(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_job_append_unit(DBusMessageIter *i, const char *property, void *data) {
Job *j = data;
DBusMessageIter sub;
char *p;
- assert(m);
assert(i);
assert(property);
assert(j);
@@ -103,7 +103,7 @@ static DBusHandlerResult bus_job_message_dispatch(Job *j, DBusConnection *connec
job_finish_and_invalidate(j, JOB_CANCELED);
} else
- return bus_default_message_handler(j->manager, connection, message, INTROSPECTION, INTERFACES_LIST, properties);
+ return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, properties);
if (reply) {
if (!dbus_connection_send(connection, reply, NULL))
@@ -201,10 +201,10 @@ static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBu
dbus_error_init(&e);
dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown job");
- return bus_send_error_reply(m, connection, message, &e, r);
+ return bus_send_error_reply(connection, message, &e, r);
}
- return bus_send_error_reply(m, connection, message, NULL, r);
+ return bus_send_error_reply(connection, message, NULL, r);
}
return bus_job_message_dispatch(j, connection, message);
diff --git a/src/dbus-manager.c b/src/dbus-manager.c
index 2f755bcc64..4224afaccb 100644
--- a/src/dbus-manager.c
+++ b/src/dbus-manager.c
@@ -28,6 +28,7 @@
#include "strv.h"
#include "bus-errors.h"
#include "build.h"
+#include "dbus-common.h"
#define BUS_MANAGER_INTERFACE_BEGIN \
" <interface name=\"org.freedesktop.systemd1.Manager\">\n"
@@ -155,8 +156,11 @@
" <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"RunningAs\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"StartupTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"StartupTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
" <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
" <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
@@ -216,13 +220,14 @@ const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFA
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_running_as, manager_running_as, ManagerRunningAs);
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
-static int bus_manager_append_tainted(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
const char *t;
- char buf[64] = "", *e = buf, *p = NULL;
+ Manager *m = data;
+ char buf[LINE_MAX] = "", *e = buf, *p = NULL;
- assert(m);
assert(i);
assert(property);
+ assert(m);
if (m->taint_usr)
e = stpcpy(e, "usr-separate-fs ");
@@ -243,10 +248,9 @@ static int bus_manager_append_tainted(Manager *m, DBusMessageIter *i, const char
return 0;
}
-static int bus_manager_append_log_target(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
const char *t;
- assert(m);
assert(i);
assert(property);
@@ -258,10 +262,9 @@ static int bus_manager_append_log_target(Manager *m, DBusMessageIter *i, const c
return 0;
}
-static int bus_manager_set_log_target(Manager *m, DBusMessageIter *i, const char *property) {
+static int bus_manager_set_log_target(DBusMessageIter *i, const char *property) {
const char *t;
- assert(m);
assert(i);
assert(property);
@@ -270,10 +273,9 @@ static int bus_manager_set_log_target(Manager *m, DBusMessageIter *i, const char
return log_set_target_from_string(t);
}
-static int bus_manager_append_log_level(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
const char *t;
- assert(m);
assert(i);
assert(property);
@@ -285,10 +287,9 @@ static int bus_manager_append_log_level(Manager *m, DBusMessageIter *i, const ch
return 0;
}
-static int bus_manager_set_log_level(Manager *m, DBusMessageIter *i, const char *property) {
+static int bus_manager_set_log_level(DBusMessageIter *i, const char *property) {
const char *t;
- assert(m);
assert(i);
assert(property);
@@ -297,12 +298,13 @@ static int bus_manager_set_log_level(Manager *m, DBusMessageIter *i, const char
return log_set_max_level_from_string(t);
}
-static int bus_manager_append_n_names(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
+ Manager *m = data;
uint32_t u;
- assert(m);
assert(i);
assert(property);
+ assert(m);
u = hashmap_size(m->units);
@@ -312,12 +314,13 @@ static int bus_manager_append_n_names(Manager *m, DBusMessageIter *i, const char
return 0;
}
-static int bus_manager_append_n_jobs(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
+ Manager *m = data;
uint32_t u;
- assert(m);
assert(i);
assert(property);
+ assert(m);
u = hashmap_size(m->jobs);
@@ -327,12 +330,13 @@ static int bus_manager_append_n_jobs(Manager *m, DBusMessageIter *i, const char
return 0;
}
-static int bus_manager_append_progress(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
double d;
+ Manager *m = data;
- assert(m);
assert(i);
assert(property);
+ assert(m);
if (dual_timestamp_is_set(&m->finish_timestamp))
d = 1.0;
@@ -369,15 +373,18 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
{ "org.freedesktop.systemd1.Manager", "RunningAs", bus_manager_append_running_as, "s", &m->running_as },
{ "org.freedesktop.systemd1.Manager", "Tainted", bus_manager_append_tainted, "s", m },
{ "org.freedesktop.systemd1.Manager", "InitRDTimestamp", bus_property_append_uint64, "t", &m->initrd_timestamp.realtime },
+ { "org.freedesktop.systemd1.Manager", "InitRDTimestampMonotonic", bus_property_append_uint64, "t", &m->initrd_timestamp.monotonic },
{ "org.freedesktop.systemd1.Manager", "StartupTimestamp", bus_property_append_uint64, "t", &m->startup_timestamp.realtime },
+ { "org.freedesktop.systemd1.Manager", "StartupTimestampMonotonic", bus_property_append_uint64, "t", &m->startup_timestamp.monotonic },
{ "org.freedesktop.systemd1.Manager", "FinishTimestamp", bus_property_append_uint64, "t", &m->finish_timestamp.realtime },
- { "org.freedesktop.systemd1.Manager", "LogLevel", bus_manager_append_log_level, "s", NULL, bus_manager_set_log_level},
- { "org.freedesktop.systemd1.Manager", "LogTarget", bus_manager_append_log_target, "s", NULL, bus_manager_set_log_target},
- { "org.freedesktop.systemd1.Manager", "NNames", bus_manager_append_n_names, "u", NULL },
+ { "org.freedesktop.systemd1.Manager", "FinishTimestampMonotonic", bus_property_append_uint64, "t",&m->finish_timestamp.monotonic },
+ { "org.freedesktop.systemd1.Manager", "LogLevel", bus_manager_append_log_level, "s", m, bus_manager_set_log_level },
+ { "org.freedesktop.systemd1.Manager", "LogTarget", bus_manager_append_log_target, "s", m, bus_manager_set_log_target },
+ { "org.freedesktop.systemd1.Manager", "NNames", bus_manager_append_n_names, "u", m },
{ "org.freedesktop.systemd1.Manager", "NJobs", bus_manager_append_n_jobs, "u", NULL },
{ "org.freedesktop.systemd1.Manager", "NInstalledJobs",bus_property_append_uint32, "u", &m->n_installed_jobs },
{ "org.freedesktop.systemd1.Manager", "NFailedJobs", bus_property_append_uint32, "u", &m->n_failed_jobs },
- { "org.freedesktop.systemd1.Manager", "Progress", bus_manager_append_progress, "d", NULL },
+ { "org.freedesktop.systemd1.Manager", "Progress", bus_manager_append_progress, "d", m },
{ "org.freedesktop.systemd1.Manager", "Environment", bus_property_append_strv, "as", m->environment },
{ "org.freedesktop.systemd1.Manager", "ConfirmSpawn", bus_property_append_bool, "b", &m->confirm_spawn },
{ "org.freedesktop.systemd1.Manager", "ShowStatus", bus_property_append_bool, "b", &m->show_status },
@@ -419,11 +426,11 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if (!(u = manager_get_unit(m, name))) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
- return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
if (!(reply = dbus_message_new_method_return(message)))
@@ -446,11 +453,11 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
&error,
DBUS_TYPE_UINT32, &pid,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
- return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
if (!(reply = dbus_message_new_method_return(message)))
@@ -473,10 +480,10 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
- return bus_send_error_reply(m, connection, message, &error, r);
+ return bus_send_error_reply(connection, message, &error, r);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
@@ -523,21 +530,21 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
DBUS_TYPE_STRING, &smode,
DBUS_TYPE_INT32, &signo,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if ((mode = kill_mode_from_string(smode)) < 0 ||
(who = kill_who_from_string(swho)) < 0 ||
signo <= 0 ||
signo >= _NSIG)
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if (!(u = manager_get_unit(m, name))) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
- return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
- return bus_send_error_reply(m, connection, message, &error, r);
+ return bus_send_error_reply(connection, message, &error, r);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
@@ -551,11 +558,11 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
&error,
DBUS_TYPE_UINT32, &id,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if (!(j = manager_get_job(m, id))) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
- return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
if (!(reply = dbus_message_new_method_return(message)))
@@ -593,11 +600,11 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if (!(u = manager_get_unit(m, name))) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
- return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
unit_reset_failed(u);
@@ -759,7 +766,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if ((r = set_put(s, client)) < 0) {
free(client);
- return bus_send_error_reply(m, connection, message, NULL, r);
+ return bus_send_error_reply(connection, message, NULL, r);
}
if (!(reply = dbus_message_new_method_return(message)))
@@ -770,7 +777,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
- return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
free(client);
@@ -817,13 +824,13 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_BOOLEAN, &cleanup,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if (name && name[0] == 0)
name = NULL;
if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
- return bus_send_error_reply(m, connection, message, &error, r);
+ return bus_send_error_reply(connection, message, &error, r);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
@@ -924,7 +931,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (m->running_as == MANAGER_SYSTEM) {
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
- return bus_send_error_reply(m, connection, message, &error, -ENOTSUP);
+ return bus_send_error_reply(connection, message, &error, -ENOTSUP);
}
if (!(reply = dbus_message_new_method_return(message)))
@@ -936,7 +943,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (m->running_as != MANAGER_SYSTEM) {
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
- return bus_send_error_reply(m, connection, message, &error, -ENOTSUP);
+ return bus_send_error_reply(connection, message, &error, -ENOTSUP);
}
if (!(reply = dbus_message_new_method_return(message)))
@@ -948,7 +955,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (m->running_as != MANAGER_SYSTEM) {
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
- return bus_send_error_reply(m, connection, message, &error, -ENOTSUP);
+ return bus_send_error_reply(connection, message, &error, -ENOTSUP);
}
if (!(reply = dbus_message_new_method_return(message)))
@@ -960,7 +967,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (m->running_as != MANAGER_SYSTEM) {
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
- return bus_send_error_reply(m, connection, message, &error, -ENOTSUP);
+ return bus_send_error_reply(connection, message, &error, -ENOTSUP);
}
if (!(reply = dbus_message_new_method_return(message)))
@@ -972,7 +979,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (m->running_as != MANAGER_SYSTEM) {
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
- return bus_send_error_reply(m, connection, message, &error, -ENOTSUP);
+ return bus_send_error_reply(connection, message, &error, -ENOTSUP);
}
if (!(reply = dbus_message_new_method_return(message)))
@@ -987,7 +994,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (r == -ENOMEM)
goto oom;
- return bus_send_error_reply(m, connection, message, NULL, r);
+ return bus_send_error_reply(connection, message, NULL, r);
}
e = strv_env_merge(2, m->environment, l);
@@ -1011,7 +1018,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (r == -ENOMEM)
goto oom;
- return bus_send_error_reply(m, connection, message, NULL, r);
+ return bus_send_error_reply(connection, message, NULL, r);
}
e = strv_env_delete(m->environment, 1, l);
@@ -1029,7 +1036,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
m->environment = e;
} else
- return bus_default_message_handler(m, connection, message, NULL, INTERFACES_LIST, properties);
+ return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, properties);
if (job_type != _JOB_TYPE_INVALID) {
const char *name, *smode, *old_name = NULL;
@@ -1055,24 +1062,24 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
DBUS_TYPE_INVALID);
if (!b)
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if (old_name)
if (!(u = manager_get_unit(m, old_name)) ||
!u->meta.job ||
u->meta.job->type != JOB_START) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
- return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
}
if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
- return bus_send_error_reply(m, connection, message, &error, r);
+ return bus_send_error_reply(connection, message, &error, r);
if (reload_if_possible && unit_can_reload(u)) {
if (job_type == JOB_RESTART)
@@ -1086,11 +1093,11 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
(u->meta.refuse_manual_start || u->meta.refuse_manual_stop))) {
dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
- return bus_send_error_reply(m, connection, message, &error, -EPERM);
+ return bus_send_error_reply(connection, message, &error, -EPERM);
}
if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
- return bus_send_error_reply(m, connection, message, &error, r);
+ return bus_send_error_reply(connection, message, &error, r);
if (!(j->bus_client = strdup(message_get_sender_with_fallback(message))))
goto oom;
diff --git a/src/dbus-mount.c b/src/dbus-mount.c
index 5fb9a3f071..cfbfd4531c 100644
--- a/src/dbus-mount.c
+++ b/src/dbus-mount.c
@@ -24,6 +24,7 @@
#include "dbus-unit.h"
#include "dbus-mount.h"
#include "dbus-execute.h"
+#include "dbus-common.h"
#define BUS_MOUNT_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Mount\">\n" \
@@ -65,11 +66,10 @@ const char bus_mount_invalidating_properties[] =
"ExecRemount\0"
"ControlPID\0";
-static int bus_mount_append_what(Manager *n, DBusMessageIter *i, const char *property, void *data) {
+static int bus_mount_append_what(DBusMessageIter *i, const char *property, void *data) {
Mount *m = data;
const char *d;
- assert(n);
assert(i);
assert(property);
assert(m);
@@ -89,11 +89,10 @@ static int bus_mount_append_what(Manager *n, DBusMessageIter *i, const char *pro
return 0;
}
-static int bus_mount_append_options(Manager *n, DBusMessageIter *i, const char *property, void *data) {
+static int bus_mount_append_options(DBusMessageIter *i, const char *property, void *data) {
Mount *m = data;
const char *d;
- assert(n);
assert(i);
assert(property);
assert(m);
@@ -113,11 +112,10 @@ static int bus_mount_append_options(Manager *n, DBusMessageIter *i, const char *
return 0;
}
-static int bus_mount_append_type(Manager *n, DBusMessageIter *i, const char *property, void *data) {
+static int bus_mount_append_type(DBusMessageIter *i, const char *property, void *data) {
Mount *m = data;
const char *d;
- assert(n);
assert(i);
assert(property);
assert(m);
@@ -138,6 +136,7 @@ static int bus_mount_append_type(Manager *n, DBusMessageIter *i, const char *pro
}
DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
+
const BusProperty properties[] = {
BUS_UNIT_PROPERTIES,
{ "org.freedesktop.systemd1.Mount", "Where", bus_property_append_string, "s", u->mount.where },
@@ -154,5 +153,5 @@ DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMess
{ NULL, NULL, NULL, NULL, NULL }
};
- return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
+ return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, properties);
}
diff --git a/src/dbus-path.c b/src/dbus-path.c
index cb1d4f09cb..15238798ae 100644
--- a/src/dbus-path.c
+++ b/src/dbus-path.c
@@ -24,11 +24,14 @@
#include "dbus-unit.h"
#include "dbus-path.h"
#include "dbus-execute.h"
+#include "dbus-common.h"
#define BUS_PATH_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Path\">\n" \
" <property name=\"Unit\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Paths\" type=\"a(ss)\" access=\"read\"/>\n" \
+ " <property name=\"MakeDirectory\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
" </interface>\n"
#define INTROSPECTION \
@@ -47,12 +50,11 @@
const char bus_path_interface[] _introspect_("Path") = BUS_PATH_INTERFACE;
-static int bus_path_append_paths(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_path_append_paths(DBusMessageIter *i, const char *property, void *data) {
Path *p = data;
DBusMessageIter sub, sub2;
PathSpec *k;
- assert(m);
assert(i);
assert(property);
assert(p);
@@ -76,11 +78,10 @@ static int bus_path_append_paths(Manager *m, DBusMessageIter *i, const char *pro
return 0;
}
-static int bus_path_append_unit(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_path_append_unit(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
const char *t;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -93,10 +94,12 @@ static int bus_path_append_unit(Manager *m, DBusMessageIter *i, const char *prop
DBusHandlerResult bus_path_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
const BusProperty properties[] = {
BUS_UNIT_PROPERTIES,
- { "org.freedesktop.systemd1.Path", "Unit", bus_path_append_unit, "s", u },
- { "org.freedesktop.systemd1.Path", "Paths", bus_path_append_paths, "a(ss)", u },
+ { "org.freedesktop.systemd1.Path", "Unit", bus_path_append_unit, "s", u },
+ { "org.freedesktop.systemd1.Path", "Paths", bus_path_append_paths, "a(ss)", u },
+ { "org.freedesktop.systemd1.Path", "MakeDirectory", bus_property_append_bool, "b", &u->path.make_directory },
+ { "org.freedesktop.systemd1.Path", "DirectoryMode", bus_property_append_mode, "u", &u->path.directory_mode },
{ NULL, NULL, NULL, NULL, NULL }
};
- return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
+ return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, properties);
}
diff --git a/src/dbus-service.c b/src/dbus-service.c
index 9c3d73cbf2..3486623e59 100644
--- a/src/dbus-service.c
+++ b/src/dbus-service.c
@@ -24,6 +24,7 @@
#include "dbus-unit.h"
#include "dbus-execute.h"
#include "dbus-service.h"
+#include "dbus-common.h"
#ifdef HAVE_SYSV_COMPAT
#define BUS_SERVICE_SYSV_INTERFACE_FRAGMENT \
@@ -129,5 +130,5 @@ DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connectio
{ NULL, NULL, NULL, NULL, NULL }
};
- return bus_default_message_handler(u->meta.manager, connection, message, INTROSPECTION, INTERFACES_LIST, properties);
+ return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, properties);
}
diff --git a/src/dbus-snapshot.c b/src/dbus-snapshot.c
index cc12b1bd8b..0c2f349599 100644
--- a/src/dbus-snapshot.c
+++ b/src/dbus-snapshot.c
@@ -21,6 +21,7 @@
#include "dbus-unit.h"
#include "dbus-snapshot.h"
+#include "dbus-common.h"
#define BUS_SNAPSHOT_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Snapshot\">\n" \
@@ -45,6 +46,7 @@
const char bus_snapshot_interface[] _introspect_("Snapshot") = BUS_SNAPSHOT_INTERFACE;
DBusHandlerResult bus_snapshot_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
+
const BusProperty properties[] = {
BUS_UNIT_PROPERTIES,
{ "org.freedesktop.systemd1.Snapshot", "Cleanup", bus_property_append_bool, "b", &u->snapshot.cleanup },
@@ -64,7 +66,7 @@ DBusHandlerResult bus_snapshot_message_handler(Unit *u, DBusConnection *c, DBusM
goto oom;
} else
- return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
+ return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, properties);
if (reply) {
if (!dbus_connection_send(c, reply, NULL))
diff --git a/src/dbus-socket.c b/src/dbus-socket.c
index 5b068b45fa..88727bbbc1 100644
--- a/src/dbus-socket.c
+++ b/src/dbus-socket.c
@@ -24,6 +24,7 @@
#include "dbus-unit.h"
#include "dbus-socket.h"
#include "dbus-execute.h"
+#include "dbus-common.h"
#define BUS_SOCKET_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Socket\">\n" \
@@ -113,5 +114,5 @@ DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMes
{ NULL, NULL, NULL, NULL, NULL }
};
- return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
+ return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, properties);
}
diff --git a/src/dbus-swap.c b/src/dbus-swap.c
index 079912a532..988ca58d4b 100644
--- a/src/dbus-swap.c
+++ b/src/dbus-swap.c
@@ -25,6 +25,7 @@
#include "dbus-unit.h"
#include "dbus-swap.h"
#include "dbus-execute.h"
+#include "dbus-common.h"
#define BUS_SWAP_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Swap\">\n" \
@@ -60,11 +61,10 @@ const char bus_swap_invalidating_properties[] =
"ExecDeactivate\0"
"ControlPID\0";
-static int bus_swap_append_priority(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_swap_append_priority(DBusMessageIter *i, const char *property, void *data) {
Swap *s = data;
dbus_int32_t j;
- assert(m);
assert(i);
assert(property);
assert(s);
@@ -96,5 +96,5 @@ DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessa
{ NULL, NULL, NULL, NULL, NULL }
};
- return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
+ return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, properties);
}
diff --git a/src/dbus-target.c b/src/dbus-target.c
index 1cbeccb579..1e00f2dbbb 100644
--- a/src/dbus-target.c
+++ b/src/dbus-target.c
@@ -23,6 +23,7 @@
#include "dbus-unit.h"
#include "dbus-target.h"
+#include "dbus-common.h"
#define BUS_TARGET_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Target\">\n" \
@@ -50,5 +51,5 @@ DBusHandlerResult bus_target_message_handler(Unit *u, DBusConnection *c, DBusMes
{ NULL, NULL, NULL, NULL, NULL }
};
- return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
+ return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, properties);
}
diff --git a/src/dbus-timer.c b/src/dbus-timer.c
index e44f4e2fea..abcbe6f9be 100644
--- a/src/dbus-timer.c
+++ b/src/dbus-timer.c
@@ -24,6 +24,7 @@
#include "dbus-unit.h"
#include "dbus-timer.h"
#include "dbus-execute.h"
+#include "dbus-common.h"
#define BUS_TIMER_INTERFACE \
" <interface name=\"org.freedesktop.systemd1.Timer\">\n" \
@@ -52,12 +53,11 @@ const char bus_timer_invalidating_properties[] =
"Timers\0"
"NextElapseUSec\0";
-static int bus_timer_append_timers(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_timer_append_timers(DBusMessageIter *i, const char *property, void *data) {
Timer *p = data;
DBusMessageIter sub, sub2;
TimerValue *k;
- assert(m);
assert(i);
assert(property);
assert(p);
@@ -99,11 +99,10 @@ static int bus_timer_append_timers(Manager *m, DBusMessageIter *i, const char *p
return 0;
}
-static int bus_timer_append_unit(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_timer_append_unit(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
const char *t;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -122,5 +121,5 @@ DBusHandlerResult bus_timer_message_handler(Unit *u, DBusConnection *c, DBusMess
{ NULL, NULL, NULL, NULL, NULL }
};
- return bus_default_message_handler(u->meta.manager, c, message, INTROSPECTION, INTERFACES_LIST, properties);
+ return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, properties);
}
diff --git a/src/dbus-unit.c b/src/dbus-unit.c
index b5daa66b5d..ad8e9a1aef 100644
--- a/src/dbus-unit.c
+++ b/src/dbus-unit.c
@@ -25,6 +25,7 @@
#include "log.h"
#include "dbus-unit.h"
#include "bus-errors.h"
+#include "dbus-common.h"
const char bus_unit_interface[] _introspect_("Unit") = BUS_UNIT_INTERFACE;
@@ -39,7 +40,7 @@ const char bus_unit_interface[] _introspect_("Unit") = BUS_UNIT_INTERFACE;
"Job\0" \
"NeedDaemonReload\0"
-int bus_unit_append_names(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_names(DBusMessageIter *i, const char *property, void *data) {
char *t;
Iterator j;
DBusMessageIter sub;
@@ -58,11 +59,10 @@ int bus_unit_append_names(Manager *m, DBusMessageIter *i, const char *property,
return 0;
}
-int bus_unit_append_following(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_following(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data, *f;
const char *d;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -76,7 +76,7 @@ int bus_unit_append_following(Manager *m, DBusMessageIter *i, const char *proper
return 0;
}
-int bus_unit_append_dependencies(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_dependencies(DBusMessageIter *i, const char *property, void *data) {
Unit *u;
Iterator j;
DBusMessageIter sub;
@@ -95,11 +95,10 @@ int bus_unit_append_dependencies(Manager *m, DBusMessageIter *i, const char *pro
return 0;
}
-int bus_unit_append_description(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_description(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
const char *d;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -114,11 +113,10 @@ int bus_unit_append_description(Manager *m, DBusMessageIter *i, const char *prop
DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_unit_append_load_state, unit_load_state, UnitLoadState);
-int bus_unit_append_active_state(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_active_state(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
const char *state;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -131,11 +129,10 @@ int bus_unit_append_active_state(Manager *m, DBusMessageIter *i, const char *pro
return 0;
}
-int bus_unit_append_sub_state(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_sub_state(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
const char *state;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -148,11 +145,10 @@ int bus_unit_append_sub_state(Manager *m, DBusMessageIter *i, const char *proper
return 0;
}
-int bus_unit_append_can_start(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_can_start(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
dbus_bool_t b;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -166,11 +162,10 @@ int bus_unit_append_can_start(Manager *m, DBusMessageIter *i, const char *proper
return 0;
}
-int bus_unit_append_can_stop(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_can_stop(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
dbus_bool_t b;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -187,11 +182,10 @@ int bus_unit_append_can_stop(Manager *m, DBusMessageIter *i, const char *propert
return 0;
}
-int bus_unit_append_can_reload(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_can_reload(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
dbus_bool_t b;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -204,11 +198,10 @@ int bus_unit_append_can_reload(Manager *m, DBusMessageIter *i, const char *prope
return 0;
}
-int bus_unit_append_can_isolate(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_can_isolate(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
dbus_bool_t b;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -222,12 +215,11 @@ int bus_unit_append_can_isolate(Manager *m, DBusMessageIter *i, const char *prop
return 0;
}
-int bus_unit_append_job(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_job(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
DBusMessageIter sub;
char *p;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -270,13 +262,12 @@ int bus_unit_append_job(Manager *m, DBusMessageIter *i, const char *property, vo
return 0;
}
-int bus_unit_append_default_cgroup(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_default_cgroup(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
char *t;
CGroupBonding *cgb;
bool success;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -295,7 +286,7 @@ int bus_unit_append_default_cgroup(Manager *m, DBusMessageIter *i, const char *p
return success ? 0 : -ENOMEM;
}
-int bus_unit_append_cgroups(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_cgroups(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
CGroupBonding *cgb;
DBusMessageIter sub;
@@ -323,11 +314,10 @@ int bus_unit_append_cgroups(Manager *m, DBusMessageIter *i, const char *property
return 0;
}
-int bus_unit_append_need_daemon_reload(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+int bus_unit_append_need_daemon_reload(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
dbus_bool_t b;
- assert(m);
assert(i);
assert(property);
assert(u);
@@ -380,16 +370,16 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
DBUS_TYPE_STRING, &smode,
DBUS_TYPE_INT32, &signo,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if ((mode = kill_mode_from_string(smode)) < 0 ||
(who = kill_who_from_string(swho)) < 0 ||
signo <= 0 ||
signo >= _NSIG)
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
- return bus_send_error_reply(m, connection, message, &error, r);
+ return bus_send_error_reply(connection, message, &error, r);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
@@ -417,7 +407,7 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
(u->meta.refuse_manual_start || u->meta.refuse_manual_stop))) {
dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
- return bus_send_error_reply(m, connection, message, &error, -EPERM);
+ return bus_send_error_reply(connection, message, &error, -EPERM);
}
if (!dbus_message_get_args(
@@ -425,7 +415,7 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
&error,
DBUS_TYPE_STRING, &smode,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if (reload_if_possible && unit_can_reload(u)) {
if (job_type == JOB_RESTART)
@@ -436,11 +426,11 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
}
if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
- return bus_send_error_reply(m, connection, message, &error, r);
+ return bus_send_error_reply(connection, message, &error, r);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
@@ -571,10 +561,10 @@ static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DB
dbus_error_init(&e);
dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown unit");
- return bus_send_error_reply(m, connection, message, &e, r);
+ return bus_send_error_reply(connection, message, &e, r);
}
- return bus_send_error_reply(m, connection, message, NULL, r);
+ return bus_send_error_reply(connection, message, NULL, r);
}
return bus_unit_message_dispatch(u, connection, message);
diff --git a/src/dbus-unit.h b/src/dbus-unit.h
index efb61797f4..a2a93235ee 100644
--- a/src/dbus-unit.h
+++ b/src/dbus-unit.h
@@ -86,23 +86,31 @@
" <property name=\"SubState\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"FragmentPath\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"InactiveExitTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"InactiveExitTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"ActiveEnterTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"ActiveEnterTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"ActiveExitTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"ActiveExitTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"InactiveEnterTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"CanReload\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"InactiveEnterTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"CanStart\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"CanStop\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"CanReload\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"CanIsolate\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"Job\" type=\"(uo)\" access=\"read\"/>\n" \
" <property name=\"StopWhenUnneeded\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"RefuseManualStart\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"RefuseManualStop\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"AllowIsolate\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"DefaultDependencies\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"OnFailureIsolate\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"IgnoreOnIsolate\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"DefaultControlGroup\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"ControlGroup\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"NeedDaemonReload\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"JobTimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"ConditionTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"ConditionTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"ConditionResult\" type=\"b\" access=\"read\"/>\n" \
" </interface>\n"
@@ -134,10 +142,14 @@
{ "org.freedesktop.systemd1.Unit", "ActiveState", bus_unit_append_active_state, "s", u }, \
{ "org.freedesktop.systemd1.Unit", "SubState", bus_unit_append_sub_state, "s", u }, \
{ "org.freedesktop.systemd1.Unit", "FragmentPath", bus_property_append_string, "s", u->meta.fragment_path }, \
- { "org.freedesktop.systemd1.Unit", "InactiveExitTimestamp",bus_property_append_usec, "t", &u->meta.inactive_exit_timestamp.realtime }, \
- { "org.freedesktop.systemd1.Unit", "ActiveEnterTimestamp", bus_property_append_usec, "t", &u->meta.active_enter_timestamp.realtime }, \
- { "org.freedesktop.systemd1.Unit", "ActiveExitTimestamp", bus_property_append_usec, "t", &u->meta.active_exit_timestamp.realtime }, \
+ { "org.freedesktop.systemd1.Unit", "InactiveExitTimestamp",bus_property_append_usec, "t", &u->meta.inactive_exit_timestamp.realtime }, \
+ { "org.freedesktop.systemd1.Unit", "InactiveExitTimestampMonotonic",bus_property_append_usec, "t", &u->meta.inactive_exit_timestamp.monotonic }, \
+ { "org.freedesktop.systemd1.Unit", "ActiveEnterTimestamp", bus_property_append_usec, "t", &u->meta.active_enter_timestamp.realtime }, \
+ { "org.freedesktop.systemd1.Unit", "ActiveEnterTimestampMonotonic", bus_property_append_usec, "t", &u->meta.active_enter_timestamp.monotonic }, \
+ { "org.freedesktop.systemd1.Unit", "ActiveExitTimestamp", bus_property_append_usec, "t", &u->meta.active_exit_timestamp.realtime }, \
+ { "org.freedesktop.systemd1.Unit", "ActiveExitTimestampMonotonic", bus_property_append_usec, "t", &u->meta.active_exit_timestamp.monotonic }, \
{ "org.freedesktop.systemd1.Unit", "InactiveEnterTimestamp",bus_property_append_usec, "t", &u->meta.inactive_enter_timestamp.realtime }, \
+ { "org.freedesktop.systemd1.Unit", "InactiveEnterTimestampMonotonic",bus_property_append_usec,"t", &u->meta.inactive_enter_timestamp.monotonic }, \
{ "org.freedesktop.systemd1.Unit", "CanStart", bus_unit_append_can_start, "b", u }, \
{ "org.freedesktop.systemd1.Unit", "CanStop", bus_unit_append_can_stop, "b", u }, \
{ "org.freedesktop.systemd1.Unit", "CanReload", bus_unit_append_can_reload, "b", u }, \
@@ -148,28 +160,31 @@
{ "org.freedesktop.systemd1.Unit", "RefuseManualStop", bus_property_append_bool, "b", &u->meta.refuse_manual_stop }, \
{ "org.freedesktop.systemd1.Unit", "AllowIsolate", bus_property_append_bool, "b", &u->meta.allow_isolate }, \
{ "org.freedesktop.systemd1.Unit", "DefaultDependencies", bus_property_append_bool, "b", &u->meta.default_dependencies }, \
+ { "org.freedesktop.systemd1.Unit", "OnFailureIsolate", bus_property_append_bool, "b", &u->meta.on_failure_isolate }, \
+ { "org.freedesktop.systemd1.Unit", "IgnoreOnIsolate", bus_property_append_bool, "b", &u->meta.ignore_on_isolate }, \
{ "org.freedesktop.systemd1.Unit", "DefaultControlGroup", bus_unit_append_default_cgroup, "s", u }, \
{ "org.freedesktop.systemd1.Unit", "ControlGroup", bus_unit_append_cgroups, "as", u }, \
{ "org.freedesktop.systemd1.Unit", "NeedDaemonReload", bus_unit_append_need_daemon_reload, "b", u }, \
{ "org.freedesktop.systemd1.Unit", "JobTimeoutUSec", bus_property_append_usec, "t", &u->meta.job_timeout }, \
{ "org.freedesktop.systemd1.Unit", "ConditionTimestamp", bus_property_append_usec, "t", &u->meta.condition_timestamp.realtime }, \
+ { "org.freedesktop.systemd1.Unit", "ConditionTimestampMonotonic", bus_property_append_usec,"t", &u->meta.condition_timestamp.monotonic }, \
{ "org.freedesktop.systemd1.Unit", "ConditionResult", bus_property_append_bool, "b", &u->meta.condition_result }
-int bus_unit_append_names(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_following(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_dependencies(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_description(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_load_state(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_active_state(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_sub_state(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_can_start(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_can_stop(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_can_reload(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_can_isolate(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_job(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_default_cgroup(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_cgroups(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_unit_append_need_daemon_reload(Manager *m, DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_names(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_following(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_dependencies(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_description(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_load_state(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_active_state(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_sub_state(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_can_start(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_can_stop(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_can_reload(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_can_isolate(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_job(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_default_cgroup(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_cgroups(DBusMessageIter *i, const char *property, void *data);
+int bus_unit_append_need_daemon_reload(DBusMessageIter *i, const char *property, void *data);
void bus_unit_send_change_signal(Unit *u);
void bus_unit_send_removed_signal(Unit *u);
diff --git a/src/dbus.c b/src/dbus.c
index 6f43c4108e..1907560bc0 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -44,6 +44,7 @@
#include "dbus-path.h"
#include "bus-errors.h"
#include "special.h"
+#include "dbus-common.h"
#define CONNECTIONS_MAX 52
@@ -69,7 +70,6 @@ const char *const bus_interface_table[] = {
NULL
};
-static const char *error_to_dbus(int error);
static void bus_done_api(Manager *m);
static void bus_done_system(Manager *m);
static void bus_done_private(Manager *m);
@@ -406,7 +406,7 @@ static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBus
if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
goto oom;
- id = error.name ? error.name : error_to_dbus(r);
+ id = error.name ? error.name : bus_errno_to_dbus(r);
text = bus_error(&error, r);
if (!dbus_message_set_destination(reply, DBUS_SERVICE_DBUS) ||
@@ -1214,289 +1214,6 @@ oom:
return -ENOMEM;
}
-DBusHandlerResult bus_default_message_handler(
- Manager *m,
- DBusConnection *c,
- DBusMessage *message,
- const char *introspection,
- const char *interfaces,
- const BusProperty *properties) {
-
- DBusError error;
- DBusMessage *reply = NULL;
- int r;
-
- assert(m);
- assert(c);
- assert(message);
-
- dbus_error_init(&error);
-
- if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect") && introspection) {
-
- if (!(reply = dbus_message_new_method_return(message)))
- goto oom;
-
- if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Get") && properties) {
- const char *interface, *property;
- const BusProperty *p;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_STRING, &property,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, c, message, &error, -EINVAL);
-
- for (p = properties; p->property; p++)
- if (streq(p->interface, interface) && streq(p->property, property))
- break;
-
- if (p->property) {
- DBusMessageIter iter, sub;
-
- if (!(reply = dbus_message_new_method_return(message)))
- goto oom;
-
- dbus_message_iter_init_append(reply, &iter);
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, p->signature, &sub))
- goto oom;
-
- if ((r = p->append(m, &sub, property, (void*) p->data)) < 0) {
-
- if (r == -ENOMEM)
- goto oom;
-
- dbus_message_unref(reply);
- return bus_send_error_reply(m, c, message, NULL, r);
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
- } else {
- if (!nulstr_contains(interfaces, interface))
- dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
- else
- dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
-
- return bus_send_error_reply(m, c, message, &error, -EINVAL);
- }
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "GetAll") && properties) {
- const char *interface;
- const BusProperty *p;
- DBusMessageIter iter, sub, sub2, sub3;
-
- if (!dbus_message_get_args(
- message,
- &error,
- DBUS_TYPE_STRING, &interface,
- DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, c, message, &error, -EINVAL);
-
- if (interface[0] && !nulstr_contains(interfaces, interface)) {
- dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
- return bus_send_error_reply(m, c, message, &error, -EINVAL);
- }
-
- if (!(reply = dbus_message_new_method_return(message)))
- goto oom;
-
- dbus_message_iter_init_append(reply, &iter);
-
- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub))
- goto oom;
-
- for (p = properties; p->property; p++) {
- if (interface[0] && !streq(p->interface, interface))
- continue;
-
- if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, NULL, &sub2) ||
- !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &p->property) ||
- !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, p->signature, &sub3))
- goto oom;
-
- if ((r = p->append(m, &sub3, p->property, (void*) p->data)) < 0) {
-
- if (r == -ENOMEM)
- goto oom;
-
- dbus_message_unref(reply);
- return bus_send_error_reply(m, c, message, NULL, r);
- }
-
- if (!dbus_message_iter_close_container(&sub2, &sub3) ||
- !dbus_message_iter_close_container(&sub, &sub2))
- goto oom;
- }
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && properties) {
- const char *interface, *property;
- DBusMessageIter iter;
- const BusProperty *p;
-
- if (!dbus_message_iter_init(message, &iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return bus_send_error_reply(m, c, message, NULL, -EINVAL);
-
- dbus_message_iter_get_basic(&iter, &interface);
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return bus_send_error_reply(m, c, message, NULL, -EINVAL);
-
- dbus_message_iter_get_basic(&iter, &property);
-
- if (!dbus_message_iter_next(&iter) ||
- dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT ||
- dbus_message_iter_has_next(&iter))
- return bus_send_error_reply(m, c, message, NULL, -EINVAL);
-
- for (p = properties; p->property; p++)
- if (streq(p->interface, interface) && streq(p->property, property))
- break;
-
- if (p->set) {
- DBusMessageIter sub;
- char *sig;
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (!(sig = dbus_message_iter_get_signature(&sub)))
- goto oom;
-
- if (!streq(sig, p->signature)) {
- dbus_free(sig);
- return bus_send_error_reply(m, c, message, NULL, -EINVAL);
- }
-
- dbus_free(sig);
-
- if ((r = p->set(m, &sub, property)) < 0) {
- if (r == -ENOMEM)
- goto oom;
- return bus_send_error_reply(m, c, message, NULL, r);
- }
-
- if (!(reply = dbus_message_new_method_return(message)))
- goto oom;
- } else {
- if (p->property)
- dbus_set_error_const(&error, DBUS_ERROR_PROPERTY_READ_ONLY, "Property read-only");
- else if (!nulstr_contains(interfaces, interface))
- dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
- else
- dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
-
- return bus_send_error_reply(m, c, message, &error, -EINVAL);
- }
-
- } else if (!nulstr_contains(interfaces, dbus_message_get_interface(message))) {
- dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
- return bus_send_error_reply(m, c, message, &error, -EINVAL);
- }
-
- if (reply) {
- if (!dbus_connection_send(c, reply, NULL))
- goto oom;
-
- dbus_message_unref(reply);
- return DBUS_HANDLER_RESULT_HANDLED;
- }
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-oom:
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&error);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-static const char *error_to_dbus(int error) {
-
- switch(error) {
-
- case -EINVAL:
- return DBUS_ERROR_INVALID_ARGS;
-
- case -ENOMEM:
- return DBUS_ERROR_NO_MEMORY;
-
- case -EPERM:
- case -EACCES:
- return DBUS_ERROR_ACCESS_DENIED;
-
- case -ESRCH:
- return DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN;
-
- case -ENOENT:
- return DBUS_ERROR_FILE_NOT_FOUND;
-
- case -EEXIST:
- return DBUS_ERROR_FILE_EXISTS;
-
- case -ETIMEDOUT:
- case -ETIME:
- return DBUS_ERROR_TIMEOUT;
-
- case -EIO:
- return DBUS_ERROR_IO_ERROR;
-
- case -ENETRESET:
- case -ECONNABORTED:
- case -ECONNRESET:
- return DBUS_ERROR_DISCONNECTED;
- }
-
- return DBUS_ERROR_FAILED;
-}
-
-DBusHandlerResult bus_send_error_reply(Manager *m, DBusConnection *c, DBusMessage *message, DBusError *berror, int error) {
- DBusMessage *reply = NULL;
- const char *name, *text;
-
- if (berror && dbus_error_is_set(berror)) {
- name = berror->name;
- text = berror->message;
- } else {
- name = error_to_dbus(error);
- text = strerror(-error);
- }
-
- if (!(reply = dbus_message_new_error(message, name, text)))
- goto oom;
-
- if (!dbus_connection_send(c, reply, NULL))
- goto oom;
-
- dbus_message_unref(reply);
-
- if (berror)
- dbus_error_free(berror);
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
- if (reply)
- dbus_message_unref(reply);
-
- if (berror)
- dbus_error_free(berror);
-
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
int bus_broadcast(Manager *m, DBusMessage *message) {
bool oom = false;
Iterator i;
@@ -1516,140 +1233,6 @@ int bus_broadcast(Manager *m, DBusMessage *message) {
return oom ? -ENOMEM : 0;
}
-int bus_property_append_string(Manager *m, DBusMessageIter *i, const char *property, void *data) {
- const char *t = data;
-
- assert(m);
- assert(i);
- assert(property);
-
- if (!t)
- t = "";
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_strv(Manager *m, DBusMessageIter *i, const char *property, void *data) {
- DBusMessageIter sub;
- char **t = data;
-
- assert(m);
- assert(i);
- assert(property);
-
- if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
- return -ENOMEM;
-
- STRV_FOREACH(t, t)
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, t))
- return -ENOMEM;
-
- if (!dbus_message_iter_close_container(i, &sub))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_bool(Manager *m, DBusMessageIter *i, const char *property, void *data) {
- bool *b = data;
- dbus_bool_t db;
-
- assert(m);
- assert(i);
- assert(property);
- assert(b);
-
- db = *b;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_uint64(Manager *m, DBusMessageIter *i, const char *property, void *data) {
- assert(m);
- assert(i);
- assert(property);
- assert(data);
-
- /* Let's ensure that pid_t is actually 64bit, and hence this
- * function can be used for usec_t */
- assert_cc(sizeof(uint64_t) == sizeof(usec_t));
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, data))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_uint32(Manager *m, DBusMessageIter *i, const char *property, void *data) {
- assert(m);
- assert(i);
- assert(property);
- assert(data);
-
- /* Let's ensure that pid_t and mode_t is actually 32bit, and
- * hence this function can be used for pid_t/mode_t */
- assert_cc(sizeof(uint32_t) == sizeof(pid_t));
- assert_cc(sizeof(uint32_t) == sizeof(mode_t));
- assert_cc(sizeof(uint32_t) == sizeof(unsigned));
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, data))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_int32(Manager *m, DBusMessageIter *i, const char *property, void *data) {
- assert(m);
- assert(i);
- assert(property);
- assert(data);
-
- assert_cc(sizeof(int32_t) == sizeof(int));
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, data))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_size(Manager *m, DBusMessageIter *i, const char *property, void *data) {
- uint64_t u;
-
- assert(m);
- assert(i);
- assert(property);
- assert(data);
-
- u = (uint64_t) *(size_t*) data;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
- return -ENOMEM;
-
- return 0;
-}
-
-int bus_property_append_ul(Manager *m, DBusMessageIter *i, const char *property, void *data) {
- uint64_t u;
-
- assert(m);
- assert(i);
- assert(property);
- assert(data);
-
- u = (uint64_t) *(unsigned long*) data;
-
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
- return -ENOMEM;
-
- return 0;
-}
-
int bus_parse_strv(DBusMessage *m, char ***_l) {
DBusMessageIter iter, sub;
unsigned n = 0, i = 0;
@@ -1722,41 +1305,3 @@ bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
}
-
-DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties) {
- DBusMessage *m;
- DBusMessageIter iter, sub;
- const char *i;
-
- assert(interface);
- assert(properties);
-
- if (!(m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged")))
- goto oom;
-
- dbus_message_iter_init_append(m, &iter);
-
- /* We won't send any property values, since they might be
- * large and sometimes not cheap to generated */
-
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
- !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
- !dbus_message_iter_close_container(&iter, &sub) ||
- !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
- goto oom;
-
- NULSTR_FOREACH(i, properties)
- if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &i))
- goto oom;
-
- if (!dbus_message_iter_close_container(&iter, &sub))
- goto oom;
-
- return m;
-
-oom:
- if (m)
- dbus_message_unref(m);
-
- return NULL;
-}
diff --git a/src/dbus.h b/src/dbus.h
index f93ad6203b..57a2b388ca 100644
--- a/src/dbus.h
+++ b/src/dbus.h
@@ -24,79 +24,8 @@
#include <dbus/dbus.h>
-#ifndef DBUS_ERROR_UNKNOWN_OBJECT
-#define DBUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject"
-#endif
-
-#ifndef DBUS_ERROR_UNKNOWN_INTERFACE
-#define DBUS_ERROR_UNKNOWN_INTERFACE "org.freedesktop.DBus.Error.UnknownInterface"
-#endif
-
-#ifndef DBUS_ERROR_UNKNOWN_PROPERTY
-#define DBUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty"
-#endif
-
-#ifndef DBUS_ERROR_PROPERTY_READ_ONLY
-#define DBUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly"
-#endif
-
#include "manager.h"
-typedef int (*BusPropertyCallback)(Manager *m, DBusMessageIter *iter, const char *property, void *data);
-typedef int (*BusPropertySetCallback)(Manager *m, DBusMessageIter *iter, const char *property);
-
-typedef struct BusProperty {
- const char *interface; /* interface of the property */
- const char *property; /* name of the property */
- BusPropertyCallback append; /* Function that is called to serialize this property */
- const char *signature;
- const void *data; /* The data of this property */
- BusPropertySetCallback set; /* Function that is called to set this property */
-} BusProperty;
-
-#define BUS_PROPERTIES_INTERFACE \
- " <interface name=\"org.freedesktop.DBus.Properties\">\n" \
- " <method name=\"Get\">\n" \
- " <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"value\" direction=\"out\" type=\"v\"/>\n" \
- " </method>\n" \
- " <method name=\"GetAll\">\n" \
- " <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n" \
- " </method>\n" \
- " <method name=\"Set\">\n" \
- " <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"value\" direction=\"in\" type=\"v\"/>\n" \
- " </method>\n" \
- " <signal name=\"PropertiesChanged\">\n" \
- " <arg type=\"s\" name=\"interface\"/>\n" \
- " <arg type=\"a{sv}\" name=\"changed_properties\"/>\n" \
- " <arg type=\"as\" name=\"invalidated_properties\"/>\n" \
- " </signal>\n" \
- " </interface>\n"
-
-#define BUS_INTROSPECTABLE_INTERFACE \
- " <interface name=\"org.freedesktop.DBus.Introspectable\">\n" \
- " <method name=\"Introspect\">\n" \
- " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" \
- " </method>\n" \
- " </interface>\n"
-
-#define BUS_PEER_INTERFACE \
- "<interface name=\"org.freedesktop.DBus.Peer\">\n" \
- " <method name=\"Ping\"/>\n" \
- " <method name=\"GetMachineId\">\n" \
- " <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n" \
- " </method>\n" \
- "</interface>\n"
-
-#define BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.DBus.Properties\0" \
- "org.freedesktop.DBus.Introspectable\0" \
- "org.freedesktop.DBus.Peer\0"
-
int bus_init(Manager *m, bool try_bus_connect);
void bus_done(Manager *m);
@@ -107,50 +36,13 @@ void bus_timeout_event(Manager *m, Watch *w, int events);
int bus_query_pid(Manager *m, const char *name);
-DBusHandlerResult bus_default_message_handler(Manager *m, DBusConnection *c, DBusMessage *message, const char* introspection, const char *interfaces, const BusProperty *properties);
-DBusHandlerResult bus_send_error_reply(Manager *m, DBusConnection *c, DBusMessage *message, DBusError *bus_error, int error);
-
int bus_broadcast(Manager *m, DBusMessage *message);
-int bus_property_append_string(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_strv(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_bool(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_int32(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_uint32(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_uint64(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_size(Manager *m, DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_ul(Manager *m, DBusMessageIter *i, const char *property, void *data);
-
-#define bus_property_append_int bus_property_append_int32
-#define bus_property_append_pid bus_property_append_uint32
-#define bus_property_append_mode bus_property_append_uint32
-#define bus_property_append_unsigned bus_property_append_uint32
-#define bus_property_append_usec bus_property_append_uint64
-
-#define DEFINE_BUS_PROPERTY_APPEND_ENUM(function,name,type) \
- int function(Manager *m, DBusMessageIter *i, const char *property, void *data) { \
- const char *value; \
- type *field = data; \
- \
- assert(m); \
- assert(i); \
- assert(property); \
- \
- value = name##_to_string(*field); \
- \
- if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &value)) \
- return -ENOMEM; \
- \
- return 0; \
- }
-
int bus_parse_strv(DBusMessage *m, char ***_l);
bool bus_has_subscriber(Manager *m);
bool bus_connection_has_subscriber(Manager *m, DBusConnection *c);
-DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties);
-
#define BUS_CONNECTION_SUBSCRIBED(m, c) dbus_connection_get_data((c), (m)->subscribed_data_slot)
#define BUS_PENDING_CALL_NAME(m, p) dbus_pending_call_get_data((p), (m)->name_data_slot)
diff --git a/src/def.h b/src/def.h
index c23cd33d8a..958d1eb79c 100644
--- a/src/def.h
+++ b/src/def.h
@@ -27,6 +27,8 @@
#define DEFAULT_TIMEOUT_USEC (3*USEC_PER_MINUTE)
#define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC)
+#define DEFAULT_EXIT_USEC (5*USEC_PER_MINUTE)
+
#define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
#define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
diff --git a/src/device.c b/src/device.c
index 41c96cef03..d507b701f1 100644
--- a/src/device.c
+++ b/src/device.c
@@ -70,6 +70,8 @@ static void device_init(Unit *u) {
* happen for the other units since their operations time out
* anyway. */
d->meta.job_timeout = DEFAULT_TIMEOUT_USEC;
+
+ d->meta.ignore_on_isolate = true;
}
static void device_done(Unit *u) {
@@ -583,7 +585,6 @@ const UnitVTable device_vtable = {
.no_instances = true,
.no_snapshots = true,
- .no_isolate = true,
.init = device_init,
diff --git a/src/execute.c b/src/execute.c
index d67916c249..745dcfcdb8 100644
--- a/src/execute.c
+++ b/src/execute.c
@@ -904,6 +904,68 @@ fail:
}
#endif
+static int do_capability_bounding_set_drop(uint64_t drop) {
+ unsigned long i;
+ cap_t old_cap = NULL, new_cap = NULL;
+ cap_flag_value_t fv;
+ int r;
+
+ /* If we are run as PID 1 we will lack CAP_SETPCAP by default
+ * in the effective set (yes, the kernel drops that when
+ * executing init!), so get it back temporarily so that we can
+ * call PR_CAPBSET_DROP. */
+
+ old_cap = cap_get_proc();
+ if (!old_cap)
+ return -errno;
+
+ if (cap_get_flag(old_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ if (fv != CAP_SET) {
+ static const cap_value_t v = CAP_SETPCAP;
+
+ new_cap = cap_dup(old_cap);
+ if (!new_cap) {
+ r = -errno;
+ goto finish;
+ }
+
+ if (cap_set_flag(new_cap, CAP_EFFECTIVE, 1, &v, CAP_SET) < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ if (cap_set_proc(new_cap) < 0) {
+ r = -errno;
+ goto finish;
+ }
+ }
+
+ for (i = 0; i <= CAP_LAST_CAP; i++)
+ if (drop & ((uint64_t) 1ULL << (uint64_t) i)) {
+ if (prctl(PR_CAPBSET_DROP, i) < 0) {
+ r = -errno;
+ goto finish;
+ }
+ }
+
+ r = 0;
+
+finish:
+ if (new_cap)
+ cap_free(new_cap);
+
+ if (old_cap) {
+ cap_set_proc(old_cap);
+ cap_free(old_cap);
+ }
+
+ return r;
+}
+
int exec_spawn(ExecCommand *command,
char **argv,
const ExecContext *context,
@@ -1106,7 +1168,8 @@ int exec_spawn(ExecCommand *command,
snprintf(t, sizeof(t), "%i", adj);
char_array_0(t);
- if (write_one_line_file("/proc/self/oom_adj", t) < 0) {
+ if (write_one_line_file("/proc/self/oom_adj", t) < 0
+ && errno != EACCES) {
r = EXIT_OOM_ADJUST;
goto fail_child;
}
@@ -1250,13 +1313,10 @@ int exec_spawn(ExecCommand *command,
}
if (context->capability_bounding_set_drop)
- for (i = 0; i <= CAP_LAST_CAP; i++)
- if (context->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) i)) {
- if (prctl(PR_CAPBSET_DROP, i) < 0) {
- r = EXIT_CAPABILITIES;
- goto fail_child;
- }
- }
+ if (do_capability_bounding_set_drop(context->capability_bounding_set_drop) < 0) {
+ r = EXIT_CAPABILITIES;
+ goto fail_child;
+ }
if (context->user)
if (enforce_user(context, uid) < 0) {
diff --git a/src/getty-generator.c b/src/getty-generator.c
index f49f9eae99..683775a4d5 100644
--- a/src/getty-generator.c
+++ b/src/getty-generator.c
@@ -86,7 +86,6 @@ int main(int argc, char *argv[]) {
if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
const char *tty;
- truncate_nl(active);
if ((tty = strrchr(active, ' ')))
tty ++;
else
diff --git a/src/gnome-ask-password-agent.vala b/src/gnome-ask-password-agent.vala
index 2bfc6a9c83..c31c07e3db 100644
--- a/src/gnome-ask-password-agent.vala
+++ b/src/gnome-ask-password-agent.vala
@@ -165,7 +165,7 @@ public class MyStatusIcon : StatusIcon {
if (not_after_as_string.scanf("%llu", out not_after) != 1)
return false;
- if (not_after < now)
+ if (not_after > 0 && not_after < now)
return false;
socket = key_file.get_string("Ask", "Socket");
diff --git a/src/hostname-setup.c b/src/hostname-setup.c
index e9869bb4df..57db9fbf7c 100644
--- a/src/hostname-setup.c
+++ b/src/hostname-setup.c
@@ -30,7 +30,7 @@
#include "util.h"
#include "log.h"
-#if defined(TARGET_FEDORA) || defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA)
+#if defined(TARGET_FEDORA) || defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA) || defined(TARGET_MEEGO)
#define FILENAME "/etc/sysconfig/network"
#elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE) || defined(TARGET_FRUGALWARE)
#define FILENAME "/etc/HOSTNAME"
@@ -40,25 +40,8 @@
#define FILENAME "/etc/conf.d/hostname"
#endif
-static char* strip_bad_chars(char *s) {
- char *p, *d;
-
- for (p = s, d = s; *p; p++)
- if ((*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z') ||
- (*p >= '0' && *p <= '9') ||
- *p == '-' ||
- *p == '_' ||
- *p == '.')
- *(d++) = *p;
-
- *d = 0;
-
- return s;
-}
-
static int read_and_strip_hostname(const char *path, char **hn) {
- char *s, *k;
+ char *s;
int r;
assert(path);
@@ -67,27 +50,21 @@ static int read_and_strip_hostname(const char *path, char **hn) {
if ((r = read_one_line_file(path, &s)) < 0)
return r;
- k = strdup(strstrip(s));
- free(s);
-
- if (!k)
- return -ENOMEM;
-
- strip_bad_chars(k);
+ hostname_cleanup(s);
- if (k[0] == 0) {
- free(k);
+ if (isempty(s)) {
+ free(s);
return -ENOENT;
}
- *hn = k;
+ *hn = s;
return 0;
}
static int read_distro_hostname(char **hn) {
-#if defined(TARGET_FEDORA) || defined(TARGET_ARCH) || defined(TARGET_GENTOO) || defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA)
+#if defined(TARGET_FEDORA) || defined(TARGET_ARCH) || defined(TARGET_GENTOO) || defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA) || defined(TARGET_MEEGO)
int r;
FILE *f;
@@ -118,9 +95,9 @@ static int read_distro_hostname(char **hn) {
goto finish;
}
- strip_bad_chars(k);
+ hostname_cleanup(k);
- if (k[0] == 0) {
+ if (isempty(k)) {
free(k);
r = -ENOENT;
goto finish;
diff --git a/src/hostnamed.c b/src/hostnamed.c
new file mode 100644
index 0000000000..8c0035a037
--- /dev/null
+++ b/src/hostnamed.c
@@ -0,0 +1,704 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2011 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <dbus/dbus.h>
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "util.h"
+#include "strv.h"
+#include "dbus-common.h"
+
+#define INTROSPECTION \
+ DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
+ "<node>\n" \
+ " <interface name=\"org.freedesktop.hostname1\">\n" \
+ " <property name=\"Hostname\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"StaticHostname\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"PrettyHostname\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"IconName\" type=\"s\" access=\"read\"/>\n" \
+ " <method name=\"SetHostname\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetStaticHostname\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetPrettyHostname\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetIconName\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " </interface>\n" \
+ BUS_PROPERTIES_INTERFACE \
+ BUS_INTROSPECTABLE_INTERFACE \
+ BUS_PEER_INTERFACE \
+ "</node>\n"
+
+#define INTERFACES_LIST \
+ BUS_GENERIC_INTERFACES_LIST \
+ "org.freedesktop.hostname1\0"
+
+enum {
+ PROP_HOSTNAME,
+ PROP_STATIC_HOSTNAME,
+ PROP_PRETTY_HOSTNAME,
+ PROP_ICON_NAME,
+ _PROP_MAX
+};
+
+static char *data[_PROP_MAX] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void free_data(void) {
+ int p;
+
+ for (p = 0; p < _PROP_MAX; p++) {
+ free(data[p]);
+ data[p] = NULL;
+ }
+}
+
+static int read_data(void) {
+ int r;
+
+ free_data();
+
+ data[PROP_HOSTNAME] = gethostname_malloc();
+ if (!data[PROP_HOSTNAME])
+ return -ENOMEM;
+
+ r = read_one_line_file("/etc/hostname", &data[PROP_STATIC_HOSTNAME]);
+ if (r < 0 && r != -ENOENT)
+ return r;
+
+ r = parse_env_file("/etc/machine-info", NEWLINE,
+ "PRETTY_HOSTNAME", &data[PROP_PRETTY_HOSTNAME],
+ "ICON_NAME", &data[PROP_ICON_NAME],
+ NULL);
+ if (r < 0 && r != -ENOENT)
+ return r;
+
+ return 0;
+}
+
+static const char* fallback_icon_name(void) {
+
+#if defined(__i386__) || defined(__x86_64__)
+ int r;
+ char *type;
+ unsigned t;
+#endif
+
+ if (detect_virtualization(NULL) > 0)
+ return "computer-vm";
+
+#if defined(__i386__) || defined(__x86_64__)
+ r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type);
+ if (r < 0)
+ return NULL;
+
+ r = safe_atou(type, &t);
+ free(type);
+
+ if (r < 0)
+ return NULL;
+
+ /* We only list the really obvious cases here. The DMI data is
+ unreliable enough, so let's not do any additional guesswork
+ on top of that.
+
+ See the SMBIOS Specification 2.7.1 section 7.4.1 for
+ details about the values listed here:
+
+ http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf
+ */
+
+ switch (t) {
+
+ case 0x3:
+ case 0x4:
+ case 0x6:
+ case 0x7:
+ return "computer-desktop";
+
+ case 0x9:
+ case 0xA:
+ case 0xE:
+ return "computer-laptop";
+
+ case 0x11:
+ case 0x1C:
+ return "computer-server";
+ }
+
+#endif
+ return NULL;
+}
+
+static int write_data_hostname(void) {
+ const char *hn;
+
+ if (isempty(data[PROP_HOSTNAME]))
+ hn = "localhost";
+ else
+ hn = data[PROP_HOSTNAME];
+
+ if (sethostname(hn, strlen(hn)) < 0)
+ return -errno;
+
+ return 0;
+}
+
+static int write_data_static_hostname(void) {
+
+ if (isempty(data[PROP_STATIC_HOSTNAME])) {
+
+ if (unlink("/etc/hostname") < 0)
+ return errno == ENOENT ? 0 : -errno;
+
+ return 0;
+ }
+
+ return write_one_line_file("/etc/hostname", data[PROP_STATIC_HOSTNAME]);
+}
+
+static int write_data_other(void) {
+
+ static const char * const name[_PROP_MAX] = {
+ [PROP_PRETTY_HOSTNAME] = "PRETTY_HOSTNAME",
+ [PROP_ICON_NAME] = "ICON_NAME"
+ };
+
+ char **l = NULL;
+ int r, p;
+
+ r = load_env_file("/etc/machine-info", &l);
+ if (r < 0 && r != -ENOENT)
+ return r;
+
+ for (p = 2; p < _PROP_MAX; p++) {
+ char *t, **u;
+
+ assert(name[p]);
+
+ if (isempty(data[p])) {
+ l = strv_env_unset(l, name[p]);
+ continue;
+ }
+
+ if (asprintf(&t, "%s=%s", name[p], strempty(data[p])) < 0) {
+ strv_free(l);
+ return -ENOMEM;
+ }
+
+ u = strv_env_set(l, t);
+ free(t);
+ strv_free(l);
+
+ if (!u)
+ return -ENOMEM;
+ l = u;
+ }
+
+ if (strv_isempty(l)) {
+
+ if (unlink("/etc/machine-info") < 0)
+ return errno == ENOENT ? 0 : -errno;
+
+ return 0;
+ }
+
+ r = write_env_file("/etc/machine-info", l);
+ strv_free(l);
+
+ return r;
+}
+
+/* This mimics dbus_bus_get_unix_user() */
+static pid_t get_unix_process_id(
+ DBusConnection *connection,
+ const char *name,
+ DBusError *error) {
+
+ DBusMessage *m = NULL, *reply = NULL;
+ uint32_t pid = 0;
+
+ m = dbus_message_new_method_call(
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "GetConnectionUnixProcessID");
+ if (!m) {
+ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto finish;
+ }
+
+ if (!dbus_message_append_args(
+ m,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID)) {
+ dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto finish;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
+ if (!reply)
+ goto finish;
+
+ if (dbus_set_error_from_message(error, reply))
+ goto finish;
+
+ if (!dbus_message_get_args(
+ reply, error,
+ DBUS_TYPE_UINT32, &pid,
+ DBUS_TYPE_INVALID))
+ goto finish;
+
+finish:
+ if (m)
+ dbus_message_unref(m);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ return (pid_t) pid;
+}
+
+static int verify_polkit(
+ DBusConnection *c,
+ DBusMessage *request,
+ const char *action,
+ bool interactive,
+ DBusError *error) {
+
+ DBusMessage *m = NULL, *reply = NULL;
+ const char *unix_process = "unix-process", *pid = "pid", *starttime = "start-time", *cancel_id = "";
+ const char *sender;
+ uint32_t flags = interactive ? 1 : 0;
+ pid_t pid_raw;
+ uint32_t pid_u32;
+ unsigned long long starttime_raw;
+ uint64_t starttime_u64;
+ DBusMessageIter iter_msg, iter_struct, iter_array, iter_dict, iter_variant;
+ int r;
+ dbus_bool_t authorized = FALSE;
+
+ assert(c);
+ assert(request);
+
+ sender = dbus_message_get_sender(request);
+ if (!sender)
+ return -EINVAL;
+
+ pid_raw = get_unix_process_id(c, sender, error);
+ if (pid_raw == 0)
+ return -EINVAL;
+
+ r = get_starttime_of_pid(pid_raw, &starttime_raw);
+ if (r < 0)
+ return r;
+
+ m = dbus_message_new_method_call(
+ "org.freedesktop.PolicyKit1",
+ "/org/freedesktop/PolicyKit1/Authority",
+ "org.freedesktop.PolicyKit1.Authority",
+ "CheckAuthorization");
+ if (!m)
+ return -ENOMEM;
+
+ dbus_message_iter_init_append(m, &iter_msg);
+
+ pid_u32 = (uint32_t) pid_raw;
+ starttime_u64 = (uint64_t) starttime_raw;
+
+ if (!dbus_message_iter_open_container(&iter_msg, DBUS_TYPE_STRUCT, NULL, &iter_struct) ||
+ !dbus_message_iter_append_basic(&iter_struct, DBUS_TYPE_STRING, &unix_process) ||
+ !dbus_message_iter_open_container(&iter_struct, DBUS_TYPE_ARRAY, "{sv}", &iter_array) ||
+ !dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) ||
+ !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &pid) ||
+ !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "u", &iter_variant) ||
+ !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT32, &pid_u32) ||
+ !dbus_message_iter_close_container(&iter_dict, &iter_variant) ||
+ !dbus_message_iter_close_container(&iter_array, &iter_dict) ||
+ !dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) ||
+ !dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &starttime) ||
+ !dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "t", &iter_variant) ||
+ !dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT64, &starttime_u64) ||
+ !dbus_message_iter_close_container(&iter_dict, &iter_variant) ||
+ !dbus_message_iter_close_container(&iter_array, &iter_dict) ||
+ !dbus_message_iter_close_container(&iter_struct, &iter_array) ||
+ !dbus_message_iter_close_container(&iter_msg, &iter_struct) ||
+ !dbus_message_iter_append_basic(&iter_msg, DBUS_TYPE_STRING, &action) ||
+ !dbus_message_iter_open_container(&iter_msg, DBUS_TYPE_ARRAY, "{ss}", &iter_array) ||
+ !dbus_message_iter_close_container(&iter_msg, &iter_array) ||
+ !dbus_message_iter_append_basic(&iter_msg, DBUS_TYPE_UINT32, &flags) ||
+ !dbus_message_iter_append_basic(&iter_msg, DBUS_TYPE_STRING, &cancel_id)) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(c, m, -1, error);
+ if (!reply) {
+ r = -EIO;
+ goto finish;
+ }
+
+ if (dbus_set_error_from_message(error, reply)) {
+ r = -EIO;
+ goto finish;
+ }
+
+ if (!dbus_message_iter_init(reply, &iter_msg) ||
+ dbus_message_iter_get_arg_type(&iter_msg) != DBUS_TYPE_STRUCT) {
+ r = -EIO;
+ goto finish;
+ }
+
+ dbus_message_iter_recurse(&iter_msg, &iter_struct);
+
+ if (dbus_message_iter_get_arg_type(&iter_struct) != DBUS_TYPE_BOOLEAN) {
+ r = -EIO;
+ goto finish;
+ }
+
+ dbus_message_iter_get_basic(&iter_struct, &authorized);
+
+ r = authorized ? 0 : -EPERM;
+
+finish:
+
+ if (m)
+ dbus_message_unref(m);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ return r;
+}
+
+static int bus_hostname_append_icon_name(DBusMessageIter *i, const char *property, void *userdata) {
+ const char *name;
+
+ assert(i);
+ assert(property);
+
+ if (isempty(data[PROP_ICON_NAME]))
+ name = fallback_icon_name();
+ else
+ name = data[PROP_ICON_NAME];
+
+ return bus_property_append_string(i, property, (void*) name);
+}
+
+static DBusHandlerResult hostname_message_handler(
+ DBusConnection *connection,
+ DBusMessage *message,
+ void *userdata) {
+
+ const BusProperty properties[] = {
+ { "org.freedesktop.hostname1", "Hostname", bus_property_append_string, "s", data[PROP_HOSTNAME]},
+ { "org.freedesktop.hostname1", "StaticHostname", bus_property_append_string, "s", data[PROP_STATIC_HOSTNAME]},
+ { "org.freedesktop.hostname1", "PrettyHostname", bus_property_append_string, "s", data[PROP_PRETTY_HOSTNAME]},
+ { "org.freedesktop.hostname1", "IconName", bus_hostname_append_icon_name, "s", data[PROP_ICON_NAME]},
+ { NULL, NULL, NULL, NULL, NULL }
+ };
+
+ DBusMessage *reply = NULL, *changed = NULL;
+ DBusError error;
+ int r;
+
+ assert(connection);
+ assert(message);
+
+ dbus_error_init(&error);
+
+ if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetHostname")) {
+ const char *name;
+ dbus_bool_t interactive;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_BOOLEAN, &interactive,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ if (isempty(name))
+ name = data[PROP_STATIC_HOSTNAME];
+
+ if (isempty(name))
+ name = "localhost";
+
+ if (!hostname_is_valid(name))
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
+
+ if (!streq_ptr(name, data[PROP_HOSTNAME])) {
+ char *h;
+
+ r = verify_polkit(connection, message, "org.freedesktop.hostname1.set-hostname", interactive, &error);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ h = strdup(name);
+ if (!h)
+ goto oom;
+
+ free(data[PROP_HOSTNAME]);
+ data[PROP_HOSTNAME] = h;
+
+ r = write_data_hostname();
+ if (r < 0) {
+ log_error("Failed to set host name: %s", strerror(-r));
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ log_info("Changed host name to '%s'", strempty(data[PROP_HOSTNAME]));
+
+ changed = bus_properties_changed_new(
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.hostname1",
+ "Hostname\0");
+ if (!changed)
+ goto oom;
+ }
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetStaticHostname")) {
+ const char *name;
+ dbus_bool_t interactive;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_BOOLEAN, &interactive,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ if (isempty(name))
+ name = NULL;
+
+ if (!streq_ptr(name, data[PROP_STATIC_HOSTNAME])) {
+
+ r = verify_polkit(connection, message, "org.freedesktop.hostname1.set-static-hostname", interactive, &error);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ if (isempty(name)) {
+ free(data[PROP_STATIC_HOSTNAME]);
+ data[PROP_STATIC_HOSTNAME] = NULL;
+ } else {
+ char *h;
+
+ if (!hostname_is_valid(name))
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
+
+ h = strdup(name);
+ if (!h)
+ goto oom;
+
+ free(data[PROP_STATIC_HOSTNAME]);
+ data[PROP_STATIC_HOSTNAME] = h;
+ }
+
+ r = write_data_static_hostname();
+ if (r < 0) {
+ log_error("Failed to write static host name: %s", strerror(-r));
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ log_info("Changed static host name to '%s'", strempty(data[PROP_HOSTNAME]));
+
+ changed = bus_properties_changed_new(
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.hostname1",
+ "StaticHostname\0");
+ if (!changed)
+ goto oom;
+ }
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetPrettyHostname") ||
+ dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetIconName")) {
+
+ const char *name;
+ dbus_bool_t interactive;
+ int k;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_BOOLEAN, &interactive,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ if (isempty(name))
+ name = NULL;
+
+ k = streq(dbus_message_get_member(message), "SetPrettyHostname") ? PROP_PRETTY_HOSTNAME : PROP_ICON_NAME;
+
+ if (!streq_ptr(name, data[k])) {
+
+ r = verify_polkit(connection, message, "org.freedesktop.hostname1.set-machine-info", interactive, &error);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, &error, r);
+
+ if (isempty(name)) {
+ free(data[k]);
+ data[k] = NULL;
+ } else {
+ char *h;
+
+ h = strdup(name);
+ if (!h)
+ goto oom;
+
+ free(data[k]);
+ data[k] = h;
+ }
+
+ r = write_data_other();
+ if (r < 0) {
+ log_error("Failed to write machine info: %s", strerror(-r));
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ log_info("Changed %s to '%s'", k == PROP_PRETTY_HOSTNAME ? "pretty host name" : "icon name", strempty(data[k]));
+
+ changed = bus_properties_changed_new(
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.hostname1",
+ k == PROP_PRETTY_HOSTNAME ? "PrettyHostname\0" : "IconName\0");
+ if (!changed)
+ goto oom;
+ }
+
+ } else
+ return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, properties);
+
+ if (!(reply = dbus_message_new_method_return(message)))
+ goto oom;
+
+ if (!dbus_connection_send(connection, reply, NULL))
+ goto oom;
+
+ dbus_message_unref(reply);
+ reply = NULL;
+
+ if (changed) {
+
+ if (!dbus_connection_send(connection, changed, NULL))
+ goto oom;
+
+ dbus_message_unref(changed);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+
+oom:
+ if (reply)
+ dbus_message_unref(reply);
+
+ if (changed)
+ dbus_message_unref(changed);
+
+ dbus_error_free(&error);
+
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+}
+
+int main(int argc, char *argv[]) {
+ const DBusObjectPathVTable hostname_vtable = {
+ .message_function = hostname_message_handler
+ };
+
+ DBusConnection *bus = NULL;
+ DBusError error;
+ int r;
+
+ dbus_error_init(&error);
+
+ log_set_target(LOG_TARGET_AUTO);
+ log_parse_environment();
+ log_open();
+
+ if (argc != 1) {
+ log_error("This program takes no arguments.");
+ r = -EINVAL;
+ goto finish;
+ }
+
+ umask(0022);
+
+ r = read_data();
+ if (r < 0) {
+ log_error("Failed to read hostname data: %s", strerror(-r));
+ goto finish;
+ }
+
+ bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
+ if (!bus) {
+ log_error("Failed to get system D-Bus connection: %s", error.message);
+ r = -ECONNREFUSED;
+ goto finish;
+ }
+
+ if (!dbus_connection_register_object_path(bus, "/org/freedesktop/hostname1", &hostname_vtable, NULL)) {
+ log_error("Not enough memory");
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ if (dbus_bus_request_name(bus, "org.freedesktop.hostname1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error) < 0) {
+ log_error("Failed to register name on bus: %s", error.message);
+ r = -EEXIST;
+ goto finish;
+ }
+
+ while (dbus_connection_read_write_dispatch(bus, -1))
+ ;
+
+ r = 0;
+
+finish:
+ free_data();
+
+ if (bus) {
+ dbus_connection_flush(bus);
+ dbus_connection_close(bus);
+ dbus_connection_unref(bus);
+ }
+
+ dbus_error_free(&error);
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/src/initctl.c b/src/initctl.c
index 15da4593d0..dd743142fd 100644
--- a/src/initctl.c
+++ b/src/initctl.c
@@ -42,9 +42,10 @@
#include "special.h"
#include "sd-daemon.h"
#include "dbus-common.h"
+#include "def.h"
#define SERVER_FD_MAX 16
-#define TIMEOUT ((int) (10*MSEC_PER_SEC))
+#define TIMEOUT_MSEC ((int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC))
typedef struct Fifo Fifo;
@@ -388,7 +389,7 @@ int main(int argc, char *argv[]) {
if ((k = epoll_wait(server.epoll_fd,
&event, 1,
- TIMEOUT)) < 0) {
+ TIMEOUT_MSEC)) < 0) {
if (errno == EINTR)
continue;
diff --git a/src/job.c b/src/job.c
index a3be7becaf..26e1a7ce99 100644
--- a/src/job.c
+++ b/src/job.c
@@ -476,6 +476,52 @@ int job_run_and_invalidate(Job *j) {
return r;
}
+static void job_print_status_message(Unit *u, JobType t, JobResult result) {
+ assert(u);
+
+ if (t == JOB_START) {
+
+ switch (result) {
+
+ case JOB_DONE:
+ unit_status_printf(u, "Started %s.\n", unit_description(u));
+ break;
+
+ case JOB_FAILED:
+ unit_status_printf(u, "Starting %s " ANSI_HIGHLIGHT_ON "failed" ANSI_HIGHLIGHT_OFF ", see 'systemctl status %s' for details.\n", unit_description(u), u->meta.id);
+ break;
+
+ case JOB_DEPENDENCY:
+ unit_status_printf(u, "Starting %s " ANSI_HIGHLIGHT_ON "aborted" ANSI_HIGHLIGHT_OFF " because a dependency failed.\n", unit_description(u));
+ break;
+
+ case JOB_TIMEOUT:
+ unit_status_printf(u, "Starting %s " ANSI_HIGHLIGHT_ON "timed out" ANSI_HIGHLIGHT_OFF ".\n", unit_description(u), u->meta.id);
+ break;
+
+ default:
+ ;
+ }
+
+ } else if (t == JOB_STOP) {
+
+ switch (result) {
+
+ case JOB_TIMEOUT:
+ unit_status_printf(u, "Stopping %s " ANSI_HIGHLIGHT_ON "timed out" ANSI_HIGHLIGHT_OFF ".\n", unit_description(u), u->meta.id);
+ break;
+
+ case JOB_DONE:
+ case JOB_FAILED:
+ unit_status_printf(u, "Stopped %s.\n", unit_description(u));
+ break;
+
+ default:
+ ;
+ }
+ }
+}
+
int job_finish_and_invalidate(Job *j, JobResult result) {
Unit *u;
Unit *other;
@@ -512,12 +558,7 @@ int job_finish_and_invalidate(Job *j, JobResult result) {
t = j->type;
job_free(j);
- if (result == JOB_FAILED && t == JOB_START)
- unit_status_printf(u, "Starting %s " ANSI_HIGHLIGHT_ON "failed" ANSI_HIGHLIGHT_OFF ", see 'systemctl status %s' for details.\n", unit_description(u), u->meta.id);
- else if (result == JOB_TIMEOUT && t == JOB_START)
- unit_status_printf(u, "Starting %s " ANSI_HIGHLIGHT_ON "timed out" ANSI_HIGHLIGHT_OFF ".\n", unit_description(u), u->meta.id);
- else if (result == JOB_TIMEOUT && t == JOB_STOP)
- unit_status_printf(u, "Stopping %s " ANSI_HIGHLIGHT_ON "timed out" ANSI_HIGHLIGHT_OFF ".\n", unit_description(u), u->meta.id);
+ job_print_status_message(u, t, result);
/* Fail depending jobs on failure */
if (result != JOB_DONE) {
@@ -563,8 +604,14 @@ int job_finish_and_invalidate(Job *j, JobResult result) {
* the unit itself. We don't tread JOB_CANCELED as failure in
* this context. And JOB_FAILURE is already handled by the
* unit itself. */
- if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY)
+ if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
+ log_notice("Job %s/%s failed with result '%s'.",
+ u->meta.id,
+ job_type_to_string(t),
+ job_result_to_string(result));
+
unit_trigger_on_failure(u);
+ }
/* Try to start the next jobs that can be started */
SET_FOREACH(other, u->meta.dependencies[UNIT_AFTER], i)
diff --git a/src/load-fragment.c b/src/load-fragment.c
index 8635bdb226..6ec5090197 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -198,7 +198,7 @@ static int config_parse_listen(
void *data,
void *userdata) {
- SocketPort *p;
+ SocketPort *p, *tail;
Socket *s;
assert(filename);
@@ -220,6 +220,26 @@ static int config_parse_listen(
}
path_kill_slashes(p->path);
+
+ } else if (streq(lvalue, "ListenSpecial")) {
+ p->type = SOCKET_SPECIAL;
+
+ if (!(p->path = strdup(rvalue))) {
+ free(p);
+ return -ENOMEM;
+ }
+
+ path_kill_slashes(p->path);
+
+ } else if (streq(lvalue, "ListenNetlink")) {
+ p->type = SOCKET_SOCKET;
+
+ if (socket_address_parse_netlink(&p->address, rvalue) < 0) {
+ log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
+ free(p);
+ return 0;
+ }
+
} else {
p->type = SOCKET_SOCKET;
@@ -246,7 +266,12 @@ static int config_parse_listen(
}
p->fd = -1;
- LIST_PREPEND(SocketPort, port, s->ports, p);
+
+ if (s->ports) {
+ LIST_FIND_TAIL(SocketPort, port, s->ports, tail);
+ LIST_INSERT_AFTER(SocketPort, port, s->ports, tail, p);
+ } else
+ LIST_PREPEND(SocketPort, port, s->ports, p);
return 0;
}
@@ -1851,6 +1876,8 @@ static int load_from_path(Unit *u, const char *path) {
{ "RefuseManualStop", config_parse_bool, 0, &u->meta.refuse_manual_stop, "Unit" },
{ "AllowIsolate", config_parse_bool, 0, &u->meta.allow_isolate, "Unit" },
{ "DefaultDependencies", config_parse_bool, 0, &u->meta.default_dependencies, "Unit" },
+ { "OnFailureIsolate", config_parse_bool, 0, &u->meta.on_failure_isolate, "Unit" },
+ { "IgnoreOnIsolate", config_parse_bool, 0, &u->meta.ignore_on_isolate, "Unit" },
{ "JobTimeoutSec", config_parse_usec, 0, &u->meta.job_timeout, "Unit" },
{ "ConditionPathExists", config_parse_condition_path, CONDITION_PATH_EXISTS, u, "Unit" },
{ "ConditionPathIsDirectory", config_parse_condition_path, CONDITION_PATH_IS_DIRECTORY, u, "Unit" },
@@ -1891,6 +1918,8 @@ static int load_from_path(Unit *u, const char *path) {
{ "ListenDatagram", config_parse_listen, 0, &u->socket, "Socket" },
{ "ListenSequentialPacket", config_parse_listen, 0, &u->socket, "Socket" },
{ "ListenFIFO", config_parse_listen, 0, &u->socket, "Socket" },
+ { "ListenNetlink", config_parse_listen, 0, &u->socket, "Socket" },
+ { "ListenSpecial", config_parse_listen, 0, &u->socket, "Socket" },
{ "BindIPv6Only", config_parse_socket_bind, 0, &u->socket, "Socket" },
{ "Backlog", config_parse_unsigned, 0, &u->socket.backlog, "Socket" },
{ "BindToDevice", config_parse_bindtodevice, 0, &u->socket, "Socket" },
@@ -1943,6 +1972,8 @@ static int load_from_path(Unit *u, const char *path) {
{ "PathChanged", config_parse_path_spec, 0, &u->path, "Path" },
{ "DirectoryNotEmpty", config_parse_path_spec, 0, &u->path, "Path" },
{ "Unit", config_parse_path_unit, 0, &u->path, "Path" },
+ { "MakeDirectory", config_parse_bool, 0, &u->path.make_directory, "Path" },
+ { "DirectoryMode", config_parse_mode, 0, &u->path.directory_mode, "Path" },
/* The [Install] section is ignored here. */
{ "Alias", NULL, 0, NULL, "Install" },
diff --git a/src/locale-setup.c b/src/locale-setup.c
index 08e289d4ee..d9adfa33f4 100644
--- a/src/locale-setup.c
+++ b/src/locale-setup.c
@@ -71,7 +71,7 @@ int locale_setup(void) {
if (detect_container(NULL) <= 0)
if ((r = parse_env_file("/proc/cmdline", WHITESPACE,
-#ifdef TARGET_FEDORA
+#if defined(TARGET_FEDORA) || defined(TARGET_MEEGO)
"LANG", &variables[VARIABLE_LANG],
#endif
"locale.LANG", &variables[VARIABLE_LANG],
@@ -116,7 +116,7 @@ int locale_setup(void) {
log_warning("Failed to read /etc/locale.conf: %s", strerror(-r));
}
-#if defined(TARGET_FEDORA) || defined(TARGET_ALTLINUX)
+#if defined(TARGET_FEDORA) || defined(TARGET_ALTLINUX) || defined(TARGET_MEEGO)
if (r <= 0 &&
(r = parse_env_file("/etc/sysconfig/i18n", NEWLINE,
"LANG", &variables[VARIABLE_LANG],
diff --git a/src/log.c b/src/log.c
index 95c27656b7..3776f0d9d8 100644
--- a/src/log.c
+++ b/src/log.c
@@ -238,11 +238,11 @@ void log_set_max_level(int level) {
}
static int write_to_console(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *buffer) {
+ int level,
+ const char*file,
+ int line,
+ const char *func,
+ const char *buffer) {
char location[64];
struct iovec iovec[5];
diff --git a/src/logger.c b/src/logger.c
index faa6c9721f..81196dbe00 100644
--- a/src/logger.c
+++ b/src/logger.c
@@ -37,10 +37,11 @@
#include "list.h"
#include "sd-daemon.h"
#include "tcpwrap.h"
+#include "def.h"
#define STREAMS_MAX 4096
#define SERVER_FD_MAX 16
-#define TIMEOUT ((int) (5*60*MSEC_PER_SEC))
+#define TIMEOUT_MSEC ((int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC))
typedef struct Stream Stream;
@@ -661,7 +662,7 @@ int main(int argc, char *argv[]) {
if ((k = epoll_wait(server.epoll_fd,
&event, 1,
- server.n_streams <= 0 ? TIMEOUT : -1)) < 0) {
+ server.n_streams <= 0 ? TIMEOUT_MSEC : -1)) < 0) {
if (errno == EINTR)
continue;
diff --git a/src/manager.c b/src/manager.c
index 9b561c4cee..9c817b0e41 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -1167,13 +1167,13 @@ static void transaction_minimize_impact(Manager *m) {
continue;
if (stops_running_service)
- log_info("%s/%s would stop a running service.", j->unit->meta.id, job_type_to_string(j->type));
+ log_debug("%s/%s would stop a running service.", j->unit->meta.id, job_type_to_string(j->type));
if (changes_existing_job)
- log_info("%s/%s would change existing job.", j->unit->meta.id, job_type_to_string(j->type));
+ log_debug("%s/%s would change existing job.", j->unit->meta.id, job_type_to_string(j->type));
/* Ok, let's get rid of this */
- log_info("Deleting %s/%s to minimize impact.", j->unit->meta.id, job_type_to_string(j->type));
+ log_debug("Deleting %s/%s to minimize impact.", j->unit->meta.id, job_type_to_string(j->type));
transaction_delete_job(m, j, true);
again = true;
@@ -1187,13 +1187,27 @@ static void transaction_minimize_impact(Manager *m) {
} while (again);
}
-static int transaction_apply(Manager *m) {
+static int transaction_apply(Manager *m, JobMode mode) {
Iterator i;
Job *j;
int r;
/* Moves the transaction jobs to the set of active jobs */
+ if (mode == JOB_ISOLATE) {
+
+ /* When isolating first kill all installed jobs which
+ * aren't part of the new transaction */
+ HASHMAP_FOREACH(j, m->jobs, i) {
+ assert(j->installed);
+
+ if (hashmap_get(m->transaction_jobs, j->unit))
+ continue;
+
+ job_finish_and_invalidate(j, JOB_CANCELED);
+ }
+ }
+
HASHMAP_FOREACH(j, m->transaction_jobs, i) {
/* Assume merged */
assert(!j->transaction_prev);
@@ -1273,7 +1287,8 @@ static int transaction_activate(Manager *m, JobMode mode, DBusError *e) {
for (;;) {
/* Fourth step: Let's remove unneeded jobs that might
* be lurking. */
- transaction_collect_garbage(m);
+ if (mode != JOB_ISOLATE)
+ transaction_collect_garbage(m);
/* Fifth step: verify order makes sense and correct
* cycles if necessary and possible */
@@ -1303,7 +1318,8 @@ static int transaction_activate(Manager *m, JobMode mode, DBusError *e) {
/* Seventh step: an entry got dropped, let's garbage
* collect its dependencies. */
- transaction_collect_garbage(m);
+ if (mode != JOB_ISOLATE)
+ transaction_collect_garbage(m);
/* Let's see if the resulting transaction still has
* unmergeable entries ... */
@@ -1320,7 +1336,7 @@ static int transaction_activate(Manager *m, JobMode mode, DBusError *e) {
}
/* Tenth step: apply changes */
- if ((r = transaction_apply(m)) < 0) {
+ if ((r = transaction_apply(m, mode)) < 0) {
log_warning("Failed to apply transaction: %s", strerror(-r));
goto rollback;
}
@@ -1617,7 +1633,7 @@ static int transaction_add_isolate_jobs(Manager *m) {
if (u->meta.id != k)
continue;
- if (UNIT_VTABLE(u)->no_isolate)
+ if (u->meta.ignore_on_isolate)
continue;
/* No need to stop inactive jobs */
@@ -2638,6 +2654,11 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds) {
assert(f);
assert(fds);
+ m->n_serializing ++;
+
+ fprintf(f, "current-job-id=%i\n", m->current_job_id);
+ fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr));
+
dual_timestamp_serialize(f, "initrd-timestamp", &m->initrd_timestamp);
dual_timestamp_serialize(f, "startup-timestamp", &m->startup_timestamp);
dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
@@ -2655,10 +2676,15 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds) {
fputs(u->meta.id, f);
fputc('\n', f);
- if ((r = unit_serialize(u, f, fds)) < 0)
+ if ((r = unit_serialize(u, f, fds)) < 0) {
+ m->n_serializing --;
return r;
+ }
}
+ assert(m->n_serializing > 0);
+ m->n_serializing --;
+
if (ferror(f))
return -EIO;
@@ -2676,7 +2702,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
m->n_deserializing ++;
for (;;) {
- char line[1024], *l;
+ char line[LINE_MAX], *l;
if (!fgets(line, sizeof(line), f)) {
if (feof(f))
@@ -2693,7 +2719,21 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
if (l[0] == 0)
break;
- if (startswith(l, "initrd-timestamp="))
+ if (startswith(l, "current-job-id=")) {
+ uint32_t id;
+
+ if (safe_atou32(l+15, &id) < 0)
+ log_debug("Failed to parse current job id value %s", l+15);
+ else
+ m->current_job_id = MAX(m->current_job_id, id);
+ } else if (startswith(l, "taint-usr=")) {
+ int b;
+
+ if ((b = parse_boolean(l+10)) < 0)
+ log_debug("Failed to parse taint /usr flag %s", l+10);
+ else
+ m->taint_usr = m->taint_usr || b;
+ } else if (startswith(l, "initrd-timestamp="))
dual_timestamp_deserialize(l+17, &m->initrd_timestamp);
else if (startswith(l, "startup-timestamp="))
dual_timestamp_deserialize(l+18, &m->startup_timestamp);
@@ -2748,15 +2788,21 @@ int manager_reload(Manager *m) {
if ((r = manager_open_serialization(m, &f)) < 0)
return r;
+ m->n_serializing ++;
+
if (!(fds = fdset_new())) {
+ m->n_serializing --;
r = -ENOMEM;
goto finish;
}
- if ((r = manager_serialize(m, f, fds)) < 0)
+ if ((r = manager_serialize(m, f, fds)) < 0) {
+ m->n_serializing --;
goto finish;
+ }
if (fseeko(f, 0, SEEK_SET) < 0) {
+ m->n_serializing --;
r = -errno;
goto finish;
}
@@ -2765,6 +2811,9 @@ int manager_reload(Manager *m) {
manager_clear_jobs_and_units(m);
manager_undo_generators(m);
+ assert(m->n_serializing > 0);
+ m->n_serializing --;
+
/* Find new unit paths */
lookup_paths_free(&m->lookup_paths);
if ((q = lookup_paths_init(&m->lookup_paths, m->running_as)) < 0)
@@ -2901,13 +2950,22 @@ void manager_run_generators(Manager *m) {
}
if (!m->generator_unit_path) {
- char *p;
- char system_path[] = "/run/systemd/generator-XXXXXX",
- user_path[] = "/tmp/systemd-generator-XXXXXX";
+ const char *p;
+ char user_path[] = "/tmp/systemd-generator-XXXXXX";
- if (!(p = mkdtemp(m->running_as == MANAGER_SYSTEM ? system_path : user_path))) {
- log_error("Failed to generate generator directory: %m");
- goto finish;
+ if (m->running_as == MANAGER_SYSTEM && getpid() == 1) {
+ p = "/run/systemd/generator";
+
+ if (mkdir_p(p, 0755) < 0) {
+ log_error("Failed to create generator directory: %m");
+ goto finish;
+ }
+
+ } else {
+ if (!(p = mkdtemp(user_path))) {
+ log_error("Failed to create generator directory: %m");
+ goto finish;
+ }
}
if (!(m->generator_unit_path = strdup(p))) {
diff --git a/src/manager.h b/src/manager.h
index 4b405d61c1..07b92c8e4e 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -223,6 +223,7 @@ struct Manager {
ExecOutput default_std_output, default_std_error;
+ int n_serializing;
int n_deserializing;
unsigned n_installed_jobs;
diff --git a/src/mount-setup.c b/src/mount-setup.c
index a42ed43957..db5c253708 100644
--- a/src/mount-setup.c
+++ b/src/mount-setup.c
@@ -55,8 +55,8 @@ static const MountPoint mount_table[] = {
{ "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV, true },
{ "devpts", "/dev/pts", "devpts", "mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC, false },
{ "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
- { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
- { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV, true },
+ { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, false },
+ { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV, false },
};
/* These are API file systems that might be mounted by other software,
@@ -64,9 +64,7 @@ static const MountPoint mount_table[] = {
static const char * const ignore_paths[] = {
"/selinux",
- "/proc/bus/usb",
- "/var/lib/nfs/rpc_pipefs",
- "/proc/fs/nfsd"
+ "/proc/bus/usb"
};
bool mount_point_is_api(const char *path) {
@@ -97,11 +95,14 @@ static int mount_one(const MountPoint *p) {
assert(p);
+ /* Relabel first, just in case */
+ label_fix(p->where, true);
+
if ((r = path_is_mount_point(p->where)) < 0)
return r;
if (r > 0)
- goto finish;
+ return 0;
/* The access mode here doesn't really matter too much, since
* the mounted file system will take precedence anyway. */
@@ -122,7 +123,7 @@ static int mount_one(const MountPoint *p) {
return p->fatal ? -errno : 0;
}
-finish:
+ /* Relabel again, since we now mounted something fresh here */
label_fix(p->where, false);
return 0;
@@ -131,7 +132,7 @@ finish:
static int mount_cgroup_controllers(void) {
int r;
FILE *f;
- char buf [256];
+ char buf[LINE_MAX];
/* Mount all available cgroup controllers that are built into the kernel. */
@@ -239,25 +240,23 @@ int mount_setup(void) {
if ((r = mount_one(mount_table+i)) < 0)
return r;
- /* Nodes in devtmpfs need to be manually updated for the
- * appropriate labels, after mounting. The other virtual API
- * file systems do not need. */
-
+ /* Nodes in devtmpfs and /run need to be manually updated for
+ * the appropriate labels, after mounting. The other virtual
+ * API file systems like /sys and /proc do not need that, they
+ * use the same label for all their files. */
if (unlink("/dev/.systemd-relabel-run-dev") >= 0) {
nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS);
nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS);
}
/* Create a few default symlinks, which are normally created
- * bei udevd, but some scripts might need them before we start
+ * by udevd, but some scripts might need them before we start
* udevd. */
-
NULSTR_FOREACH_PAIR(j, k, symlinks)
symlink_and_label(j, k);
/* Create a few directories we always want around */
mkdir("/run/systemd", 0755);
- mkdir("/run/systemd/ask-password", 0755);
return mount_cgroup_controllers();
}
diff --git a/src/mount.c b/src/mount.c
index 49bfd079a6..4b300364af 100644
--- a/src/mount.c
+++ b/src/mount.c
@@ -65,7 +65,11 @@ static void mount_init(Unit *u) {
m->directory_mode = 0755;
exec_context_init(&m->exec_context);
- m->exec_context.std_output = EXEC_OUTPUT_KMSG;
+
+ /* The stdio/kmsg bridge socket is on /, in order to avoid a
+ * dep loop, don't use kmsg logging for -.mount */
+ if (!unit_has_name(u, "-.mount"))
+ m->exec_context.std_output = EXEC_OUTPUT_KMSG;
/* We need to make sure that /bin/mount is always called in
* the same process group as us, so that the autofs kernel
@@ -76,6 +80,8 @@ static void mount_init(Unit *u) {
m->timer_watch.type = WATCH_INVALID;
m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
+
+ m->meta.ignore_on_isolate = true;
}
static void mount_unwatch_control_pid(Mount *m) {
@@ -317,7 +323,7 @@ static bool needs_quota(MountParameters *p) {
mount_test_option(p->options, "grpquota");
}
-static int mount_add_target_links(Mount *m) {
+static int mount_add_fstab_links(Mount *m) {
const char *target, *after = NULL;
MountParameters *p;
Unit *tu;
@@ -326,27 +332,36 @@ static int mount_add_target_links(Mount *m) {
assert(m);
+ if (m->meta.manager->running_as != MANAGER_SYSTEM)
+ return 0;
+
if (!(p = get_mount_parameters_configured(m)))
return 0;
- noauto = !!mount_test_option(p->options, MNTOPT_NOAUTO);
+ if (p != &m->parameters_etc_fstab)
+ return 0;
+
+ noauto = !!mount_test_option(p->options, "noauto");
nofail = !!mount_test_option(p->options, "nofail");
+ automount =
+ mount_test_option(p->options, "comment=systemd.automount") ||
+ mount_test_option(p->options, "x-systemd-automount");
handle =
+ automount ||
mount_test_option(p->options, "comment=systemd.mount") ||
mount_test_option(p->options, "x-systemd-mount") ||
m->meta.manager->mount_auto;
- automount =
- mount_test_option(p->options, "comment=systemd.automount") ||
- mount_test_option(p->options, "x-systemd-automount");
if (mount_is_network(p)) {
target = SPECIAL_REMOTE_FS_TARGET;
-
- if (m->meta.manager->running_as == MANAGER_SYSTEM)
- after = SPECIAL_NETWORK_TARGET;
+ after = SPECIAL_NETWORK_TARGET;
} else
target = SPECIAL_LOCAL_FS_TARGET;
+ if (!path_equal(m->where, "/"))
+ if ((r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true)) < 0)
+ return r;
+
if ((r = manager_load_unit(m->meta.manager, target, NULL, NULL, &tu)) < 0)
return r;
@@ -354,27 +369,36 @@ static int mount_add_target_links(Mount *m) {
if ((r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true)) < 0)
return r;
- if (automount && m->meta.manager->running_as == MANAGER_SYSTEM) {
+ if (automount) {
Unit *am;
if ((r = unit_load_related_unit(UNIT(m), ".automount", &am)) < 0)
return r;
- return unit_add_two_dependencies(tu, UNIT_AFTER, UNIT_WANTS, UNIT(am), true);
- } else {
+ /* If auto is configured as well also pull in the
+ * mount right-away, but don't rely on it. */
+ if (!noauto) /* automount + auto */
+ if ((r = unit_add_dependency(tu, UNIT_WANTS, UNIT(m), true)) < 0)
+ return r;
+
+ /* Install automount unit */
+ if (!nofail) /* automount + fail */
+ return unit_add_two_dependencies(tu, UNIT_AFTER, UNIT_REQUIRES, UNIT(am), true);
+ else /* automount + nofail */
+ return unit_add_two_dependencies(tu, UNIT_AFTER, UNIT_WANTS, UNIT(am), true);
+
+ } else if (handle && !noauto) {
/* Automatically add mount points that aren't natively
* configured to local-fs.target */
- if (!noauto &&
- !nofail &&
- handle &&
- m->from_etc_fstab &&
- m->meta.manager->running_as == MANAGER_SYSTEM)
- if ((r = unit_add_dependency(tu, UNIT_WANTS, UNIT(m), true)) < 0)
- return r;
- return unit_add_dependency(UNIT(m), UNIT_BEFORE, tu, true);
+ if (!nofail) /* auto + fail */
+ return unit_add_two_dependencies(tu, UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
+ else /* auto + nofail */
+ return unit_add_dependency(tu, UNIT_WANTS, UNIT(m), true);
}
+
+ return 0;
}
static int mount_add_device_links(Mount *m) {
@@ -389,10 +413,12 @@ static int mount_add_device_links(Mount *m) {
if (!p->what)
return 0;
- if (!mount_is_bind(p) && !path_equal(m->where, "/")) {
+ if (!mount_is_bind(p) &&
+ !path_equal(m->where, "/") &&
+ p == &m->parameters_etc_fstab) {
bool nofail, noauto;
- noauto = !!mount_test_option(p->options, MNTOPT_NOAUTO);
+ noauto = !!mount_test_option(p->options, "noauto");
nofail = !!mount_test_option(p->options, "nofail");
if ((r = unit_add_node_link(UNIT(m), p->what,
@@ -454,6 +480,54 @@ static int mount_add_default_dependencies(Mount *m) {
return 0;
}
+static int mount_fix_timeouts(Mount *m) {
+ MountParameters *p;
+ const char *timeout = NULL;
+ Unit *other;
+ Iterator i;
+ usec_t u;
+ char *t;
+ int r;
+
+ assert(m);
+
+ if (!(p = get_mount_parameters_configured(m)))
+ return 0;
+
+ /* Allow configuration how long we wait for a device that
+ * backs a mount point to show up. This is useful to support
+ * endless device timeouts for devices that show up only after
+ * user input, like crypto devices. */
+
+ if ((timeout = mount_test_option(p->options, "comment=systemd.device-timeout")))
+ timeout += 31;
+ else if ((timeout = mount_test_option(p->options, "x-systemd-device-timeout")))
+ timeout += 25;
+ else
+ return 0;
+
+ t = strndup(timeout, strcspn(timeout, ",;" WHITESPACE));
+ if (!t)
+ return -ENOMEM;
+
+ r = parse_usec(t, &u);
+ free(t);
+
+ if (r < 0) {
+ log_warning("Failed to parse timeout for %s, ignoring: %s", m->where, timeout);
+ return r;
+ }
+
+ SET_FOREACH(other, m->meta.dependencies[UNIT_AFTER], i) {
+ if (other->meta.type != UNIT_DEVICE)
+ continue;
+
+ other->meta.job_timeout = u;
+ }
+
+ return 0;
+}
+
static int mount_verify(Mount *m) {
bool b;
char *e;
@@ -511,6 +585,8 @@ static int mount_load(Unit *u) {
if (m->meta.fragment_path)
m->from_fragment = true;
+ else if (m->from_etc_fstab)
+ m->meta.default_dependencies = false;
if (!m->where)
if (!(m->where = unit_name_to_path(u->meta.id)))
@@ -540,15 +616,17 @@ static int mount_load(Unit *u) {
if ((r = mount_add_automount_links(m)) < 0)
return r;
- if ((r = mount_add_target_links(m)) < 0)
- return r;
-
- if ((r = unit_add_default_cgroups(u)) < 0)
+ if ((r = mount_add_fstab_links(m)) < 0)
return r;
if (m->meta.default_dependencies)
if ((r = mount_add_default_dependencies(m)) < 0)
return r;
+
+ if ((r = unit_add_default_cgroups(u)) < 0)
+ return r;
+
+ mount_fix_timeouts(m);
}
return mount_verify(m);
@@ -1454,7 +1532,7 @@ static int mount_load_etc_fstab(Manager *m) {
what,
NULL,
pri,
- !!mount_test_option(me->mnt_opts, MNTOPT_NOAUTO),
+ !!mount_test_option(me->mnt_opts, "noauto"),
!!mount_test_option(me->mnt_opts, "nofail"),
!!mount_test_option(me->mnt_opts, "comment=systemd.swapon"),
false);
@@ -1759,7 +1837,6 @@ const UnitVTable mount_vtable = {
.no_alias = true,
.no_instances = true,
- .no_isolate = true,
.show_status = true,
.init = mount_init,
diff --git a/src/nspawn.c b/src/nspawn.c
index 6b0ba4e57f..969c961895 100644
--- a/src/nspawn.c
+++ b/src/nspawn.c
@@ -374,6 +374,7 @@ static int is_os_tree(const char *path) {
#define BUFFER_SIZE 1024
static int process_pty(int master, sigset_t *mask) {
+
char in_buffer[BUFFER_SIZE], out_buffer[BUFFER_SIZE];
size_t in_buffer_full = 0, out_buffer_full = 0;
struct epoll_event stdin_ev, stdout_ev, master_ev, signal_ev;
@@ -464,11 +465,13 @@ static int process_pty(int master, sigset_t *mask) {
if ((n = read(signal_fd, &sfsi, sizeof(sfsi))) != sizeof(sfsi)) {
if (n >= 0) {
+ log_error("Failed to read from signalfd: invalid block size");
r = -EIO;
goto finish;
}
if (errno != EINTR && errno != EAGAIN) {
+ log_error("Failed to read from signalfd: %m");
r = -errno;
goto finish;
}
@@ -481,7 +484,7 @@ static int process_pty(int master, sigset_t *mask) {
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
ioctl(master, TIOCSWINSZ, &ws);
} else {
- r = -EINTR;
+ r = 0;
goto finish;
}
}
@@ -501,6 +504,7 @@ static int process_pty(int master, sigset_t *mask) {
stdin_readable = false;
else {
log_error("read(): %m");
+ r = -errno;
goto finish;
}
} else
@@ -515,6 +519,7 @@ static int process_pty(int master, sigset_t *mask) {
master_writable = false;
else {
log_error("write(): %m");
+ r = -errno;
goto finish;
}
@@ -533,6 +538,7 @@ static int process_pty(int master, sigset_t *mask) {
master_readable = false;
else {
log_error("read(): %m");
+ r = -errno;
goto finish;
}
} else
@@ -547,6 +553,7 @@ static int process_pty(int master, sigset_t *mask) {
stdout_writable = false;
else {
log_error("write(): %m");
+ r = -errno;
goto finish;
}
diff --git a/src/org.freedesktop.hostname1.conf b/src/org.freedesktop.hostname1.conf
new file mode 100644
index 0000000000..eb241c022f
--- /dev/null
+++ b/src/org.freedesktop.hostname1.conf
@@ -0,0 +1,27 @@
+<?xml version="1.0"?> <!--*-nxml-*-->
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+<!--
+ This file is part of systemd.
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+-->
+
+<busconfig>
+
+ <policy user="root">
+ <allow own="org.freedesktop.hostname1"/>
+ <allow send_destination="org.freedesktop.hostname1"/>
+ <allow receive_sender="org.freedesktop.hostname1"/>
+ </policy>
+
+ <policy context="default">
+ <allow send_destination="org.freedesktop.hostname1"/>
+ <allow receive_sender="org.freedesktop.hostname1"/>
+ </policy>
+
+</busconfig>
diff --git a/src/org.freedesktop.hostname1.policy b/src/org.freedesktop.hostname1.policy
new file mode 100644
index 0000000000..148874fc89
--- /dev/null
+++ b/src/org.freedesktop.hostname1.policy
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+
+<!--
+ This file is part of systemd.
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+-->
+
+<policyconfig>
+
+ <vendor>The systemd Project</vendor>
+ <vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
+
+ <action id="org.freedesktop.hostname1.set-hostname">
+ <description>Set host name</description>
+ <message>Authentication is required to set the local host name.</message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.freedesktop.hostname1.set-static-hostname">
+ <description>Set static host name</description>
+ <message>Authentication is required to set the statically configured local host name.</message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.freedesktop.hostname1.set-machine-info">
+ <description>Set machine information</description>
+ <message>Authentication is required to set local machine information.</message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+</policyconfig>
diff --git a/src/org.freedesktop.hostname1.service b/src/org.freedesktop.hostname1.service
new file mode 100644
index 0000000000..42e4adb2c9
--- /dev/null
+++ b/src/org.freedesktop.hostname1.service
@@ -0,0 +1,12 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+[D-BUS Service]
+Name=org.freedesktop.hostname1
+Exec=/bin/false
+User=root
+SystemdService=dbus-org.freedesktop.hostname1.service
diff --git a/src/org.freedesktop.systemd1.policy.in b/src/org.freedesktop.systemd1.policy.in
index b8b354726b..52a28d40ea 100644
--- a/src/org.freedesktop.systemd1.policy.in
+++ b/src/org.freedesktop.systemd1.policy.in
@@ -16,7 +16,7 @@
<vendor>The systemd Project</vendor>
<vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
- <action id="org.freedesktop.systemd1.ReplyPassword">
+ <action id="org.freedesktop.systemd1.reply-password">
<description>Send passphrase back to system</description>
<message>Authentication is required to send the entered passphrase back to the system.</message>
<defaults>
@@ -27,7 +27,7 @@
<annotate key="org.freedesktop.policykit.exec.path">@rootlibexecdir@/systemd-reply-password</annotate>
</action>
- <action id="org.freedesktop.systemd1.BusAccess">
+ <action id="org.freedesktop.systemd1.bus-access">
<description>Privileged system and service manager access</description>
<message>Authentication is required to access the system and service manager.</message>
<defaults>
diff --git a/src/pam-module.c b/src/pam-module.c
index 6486546e6d..93eb929569 100644
--- a/src/pam-module.c
+++ b/src/pam-module.c
@@ -24,6 +24,7 @@
#include <sys/file.h>
#include <pwd.h>
#include <endian.h>
+#include <sys/capability.h>
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
@@ -220,18 +221,19 @@ static uint64_t get_session_id(int *mode) {
/* First attempt: let's use the session ID of the audit
* system, if it is available. */
- if (read_one_line_file("/proc/self/sessionid", &s) >= 0) {
- uint32_t u;
- int r;
+ if (have_effective_cap(CAP_AUDIT_CONTROL) > 0)
+ if (read_one_line_file("/proc/self/sessionid", &s) >= 0) {
+ uint32_t u;
+ int r;
- r = safe_atou32(s, &u);
- free(s);
+ r = safe_atou32(s, &u);
+ free(s);
- if (r >= 0 && u != (uint32_t) -1 && u > 0) {
- *mode = SESSION_ID_AUDIT;
- return (uint64_t) u;
+ if (r >= 0 && u != (uint32_t) -1 && u > 0) {
+ *mode = SESSION_ID_AUDIT;
+ return (uint64_t) u;
+ }
}
- }
/* Second attempt, use our own counter. */
if ((fd = open_file_and_lock(RUNTIME_DIR "/user/.pam-systemd-session")) >= 0) {
@@ -288,15 +290,24 @@ static int get_user_data(
assert(ret_username);
assert(ret_pw);
- if (read_one_line_file("/proc/self/loginuid", &s) >= 0) {
- uint32_t u;
+ if (have_effective_cap(CAP_AUDIT_CONTROL) > 0) {
+ /* Only use audit login uid if we are executed with
+ * sufficient capabilities so that pam_loginuid could
+ * do its job. If we are lacking the CAP_AUDIT_CONTROL
+ * capabality we most likely are being run in a
+ * container and /proc/self/loginuid is useless since
+ * it probably contains a uid of the host system. */
- r = safe_atou32(s, &u);
- free(s);
+ if (read_one_line_file("/proc/self/loginuid", &s) >= 0) {
+ uint32_t u;
- if (r >= 0 && u != (uint32_t) -1 && u > 0) {
- have_loginuid = true;
- pw = pam_modutil_getpwuid(handle, u);
+ r = safe_atou32(s, &u);
+ free(s);
+
+ if (r >= 0 && u != (uint32_t) -1 && u > 0) {
+ have_loginuid = true;
+ pw = pam_modutil_getpwuid(handle, u);
+ }
}
}
diff --git a/src/path.c b/src/path.c
index f7878b56ae..1a3e28f89f 100644
--- a/src/path.c
+++ b/src/path.c
@@ -39,6 +39,15 @@ static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
[PATH_FAILED] = UNIT_FAILED
};
+static void path_init(Unit *u) {
+ Path *p = PATH(u);
+
+ assert(u);
+ assert(u->meta.load_state == UNIT_STUB);
+
+ p->directory_mode = 0755;
+}
+
static void path_unwatch_one(Path *p, PathSpec *s) {
if (s->inotify_fd < 0)
@@ -169,9 +178,13 @@ static void path_dump(Unit *u, FILE *f, const char *prefix) {
fprintf(f,
"%sPath State: %s\n"
- "%sUnit: %s\n",
+ "%sUnit: %s\n"
+ "%sMakeDirectory: %s\n"
+ "%sDirectoryMode: %04o\n",
prefix, path_state_to_string(p->state),
- prefix, p->unit->meta.id);
+ prefix, p->unit->meta.id,
+ prefix, yes_no(p->make_directory),
+ prefix, p->directory_mode);
LIST_FOREACH(spec, s, p->specs)
fprintf(f,
@@ -408,6 +421,25 @@ fail:
path_enter_dead(p, false);
}
+static void path_mkdir(Path *p) {
+ PathSpec *s;
+
+ assert(p);
+
+ if (!p->make_directory)
+ return;
+
+ LIST_FOREACH(spec, s, p->specs) {
+ int r;
+
+ if (s->type == PATH_EXISTS)
+ continue;
+
+ if ((r = mkdir_p(s->path, p->directory_mode)) < 0)
+ log_warning("mkdir(%s) failed: %s", s->path, strerror(-r));
+ }
+}
+
static int path_start(Unit *u) {
Path *p = PATH(u);
@@ -417,6 +449,8 @@ static int path_start(Unit *u) {
if (p->unit->meta.load_state != UNIT_LOADED)
return -ENOENT;
+ path_mkdir(p);
+
p->failure = false;
path_enter_waiting(p, true, true, false);
@@ -639,6 +673,7 @@ DEFINE_STRING_TABLE_LOOKUP(path_type, PathType);
const UnitVTable path_vtable = {
.suffix = ".path",
+ .init = path_init,
.done = path_done,
.load = path_load,
diff --git a/src/path.h b/src/path.h
index 0dff120331..8ba0ce6890 100644
--- a/src/path.h
+++ b/src/path.h
@@ -70,6 +70,9 @@ struct Path {
bool failure;
bool inotify_triggered;
+
+ bool make_directory;
+ mode_t directory_mode;
};
void path_unit_notify(Unit *u, UnitActiveState new_state);
diff --git a/src/readahead-common.c b/src/readahead-common.c
index fc49a33109..8a75b2e135 100644
--- a/src/readahead-common.c
+++ b/src/readahead-common.c
@@ -209,7 +209,6 @@ finish:
return m;
}
-
#define BUMP_REQUEST_NR (16*1024)
int bump_request_nr(const char *p) {
diff --git a/src/reply-password.c b/src/reply-password.c
index 575a437645..bd55e65f3c 100644
--- a/src/reply-password.c
+++ b/src/reply-password.c
@@ -82,7 +82,7 @@ int main(int argc, char *argv[]) {
}
truncate_nl(packet+1);
- length = strlen(packet+1) + 1;
+ length = 1 + strlen(packet+1) + 1;
} else if (streq(argv[1], "0")) {
packet[0] = '-';
length = 1;
diff --git a/src/service.c b/src/service.c
index 7f8d005f00..0845d21bad 100644
--- a/src/service.c
+++ b/src/service.c
@@ -1470,7 +1470,7 @@ static void service_set_state(Service *s, ServiceState state) {
/* For the inactive states unit_notify() will trim the cgroup,
* but for exit we have to do that ourselves... */
- if (state == SERVICE_EXITED)
+ if (state == SERVICE_EXITED && s->meta.manager->n_deserializing <= 0)
cgroup_bonding_trim_list(s->meta.cgroup_bondings, true);
if (old_state != state)
diff --git a/src/socket-util.c b/src/socket-util.c
index 9b4a1b3b48..779850d37f 100644
--- a/src/socket-util.c
+++ b/src/socket-util.c
@@ -189,50 +189,102 @@ int socket_address_parse(SocketAddress *a, const char *s) {
return 0;
}
+int socket_address_parse_netlink(SocketAddress *a, const char *s) {
+ int family;
+ unsigned group = 0;
+ char* sfamily = NULL;
+ assert(a);
+ assert(s);
+
+ zero(*a);
+ a->type = SOCK_RAW;
+
+ errno = 0;
+ if (sscanf(s, "%ms %u", &sfamily, &group) < 1)
+ return errno ? -errno : -EINVAL;
+
+ if ((family = netlink_family_from_string(sfamily)) < 0)
+ if (safe_atoi(sfamily, &family) < 0) {
+ free(sfamily);
+ return -EINVAL;
+ }
+
+ free(sfamily);
+
+ a->sockaddr.nl.nl_family = AF_NETLINK;
+ a->sockaddr.nl.nl_groups = group;
+
+ a->type = SOCK_RAW;
+ a->size = sizeof(struct sockaddr_nl);
+ a->protocol = family;
+
+ return 0;
+}
+
int socket_address_verify(const SocketAddress *a) {
assert(a);
switch (socket_address_family(a)) {
- case AF_INET:
- if (a->size != sizeof(struct sockaddr_in))
- return -EINVAL;
- if (a->sockaddr.in4.sin_port == 0)
- return -EINVAL;
+ case AF_INET:
+ if (a->size != sizeof(struct sockaddr_in))
+ return -EINVAL;
- return 0;
+ if (a->sockaddr.in4.sin_port == 0)
+ return -EINVAL;
- case AF_INET6:
- if (a->size != sizeof(struct sockaddr_in6))
- return -EINVAL;
+ if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
+ return -EINVAL;
- if (a->sockaddr.in6.sin6_port == 0)
- return -EINVAL;
+ return 0;
+
+ case AF_INET6:
+ if (a->size != sizeof(struct sockaddr_in6))
+ return -EINVAL;
- return 0;
+ if (a->sockaddr.in6.sin6_port == 0)
+ return -EINVAL;
- case AF_UNIX:
- if (a->size < offsetof(struct sockaddr_un, sun_path))
- return -EINVAL;
+ if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
+ return -EINVAL;
- if (a->size > offsetof(struct sockaddr_un, sun_path)) {
+ return 0;
- if (a->sockaddr.un.sun_path[0] != 0) {
- char *e;
+ case AF_UNIX:
+ if (a->size < offsetof(struct sockaddr_un, sun_path))
+ return -EINVAL;
- /* path */
- if (!(e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path))))
- return -EINVAL;
+ if (a->size > offsetof(struct sockaddr_un, sun_path)) {
- if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
- return -EINVAL;
- }
+ if (a->sockaddr.un.sun_path[0] != 0) {
+ char *e;
+
+ /* path */
+ if (!(e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path))))
+ return -EINVAL;
+
+ if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
+ return -EINVAL;
}
+ }
- return 0;
+ if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET)
+ return -EINVAL;
- default:
- return -EAFNOSUPPORT;
+ return 0;
+
+ case AF_NETLINK:
+
+ if (a->size != sizeof(struct sockaddr_nl))
+ return -EINVAL;
+
+ if (a->type != SOCK_RAW && a->type != SOCK_DGRAM)
+ return -EINVAL;
+
+ return 0;
+
+ default:
+ return -EAFNOSUPPORT;
}
}
@@ -245,74 +297,89 @@ int socket_address_print(const SocketAddress *a, char **p) {
return r;
switch (socket_address_family(a)) {
- case AF_INET: {
- char *ret;
- if (!(ret = new(char, INET_ADDRSTRLEN+1+5+1)))
- return -ENOMEM;
+ case AF_INET: {
+ char *ret;
- if (!inet_ntop(AF_INET, &a->sockaddr.in4.sin_addr, ret, INET_ADDRSTRLEN)) {
- free(ret);
- return -errno;
- }
+ if (!(ret = new(char, INET_ADDRSTRLEN+1+5+1)))
+ return -ENOMEM;
- sprintf(strchr(ret, 0), ":%u", ntohs(a->sockaddr.in4.sin_port));
- *p = ret;
- return 0;
+ if (!inet_ntop(AF_INET, &a->sockaddr.in4.sin_addr, ret, INET_ADDRSTRLEN)) {
+ free(ret);
+ return -errno;
}
- case AF_INET6: {
- char *ret;
+ sprintf(strchr(ret, 0), ":%u", ntohs(a->sockaddr.in4.sin_port));
+ *p = ret;
+ return 0;
+ }
- if (!(ret = new(char, 1+INET6_ADDRSTRLEN+2+5+1)))
- return -ENOMEM;
+ case AF_INET6: {
+ char *ret;
- ret[0] = '[';
- if (!inet_ntop(AF_INET6, &a->sockaddr.in6.sin6_addr, ret+1, INET6_ADDRSTRLEN)) {
- free(ret);
- return -errno;
- }
+ if (!(ret = new(char, 1+INET6_ADDRSTRLEN+2+5+1)))
+ return -ENOMEM;
- sprintf(strchr(ret, 0), "]:%u", ntohs(a->sockaddr.in6.sin6_port));
- *p = ret;
- return 0;
+ ret[0] = '[';
+ if (!inet_ntop(AF_INET6, &a->sockaddr.in6.sin6_addr, ret+1, INET6_ADDRSTRLEN)) {
+ free(ret);
+ return -errno;
}
- case AF_UNIX: {
- char *ret;
+ sprintf(strchr(ret, 0), "]:%u", ntohs(a->sockaddr.in6.sin6_port));
+ *p = ret;
+ return 0;
+ }
- if (a->size <= offsetof(struct sockaddr_un, sun_path)) {
+ case AF_UNIX: {
+ char *ret;
- if (!(ret = strdup("<unamed>")))
- return -ENOMEM;
+ if (a->size <= offsetof(struct sockaddr_un, sun_path)) {
- } else if (a->sockaddr.un.sun_path[0] == 0) {
- /* abstract */
+ if (!(ret = strdup("<unnamed>")))
+ return -ENOMEM;
- /* FIXME: We assume we can print the
- * socket path here and that it hasn't
- * more than one NUL byte. That is
- * actually an invalid assumption */
+ } else if (a->sockaddr.un.sun_path[0] == 0) {
+ /* abstract */
- if (!(ret = new(char, sizeof(a->sockaddr.un.sun_path)+1)))
- return -ENOMEM;
+ /* FIXME: We assume we can print the
+ * socket path here and that it hasn't
+ * more than one NUL byte. That is
+ * actually an invalid assumption */
- ret[0] = '@';
- memcpy(ret+1, a->sockaddr.un.sun_path+1, sizeof(a->sockaddr.un.sun_path)-1);
- ret[sizeof(a->sockaddr.un.sun_path)] = 0;
+ if (!(ret = new(char, sizeof(a->sockaddr.un.sun_path)+1)))
+ return -ENOMEM;
- } else {
+ ret[0] = '@';
+ memcpy(ret+1, a->sockaddr.un.sun_path+1, sizeof(a->sockaddr.un.sun_path)-1);
+ ret[sizeof(a->sockaddr.un.sun_path)] = 0;
- if (!(ret = strdup(a->sockaddr.un.sun_path)))
- return -ENOMEM;
- }
+ } else {
- *p = ret;
- return 0;
+ if (!(ret = strdup(a->sockaddr.un.sun_path)))
+ return -ENOMEM;
}
- default:
- return -EINVAL;
+ *p = ret;
+ return 0;
+ }
+
+ case AF_NETLINK: {
+ const char *sfamily;
+
+ if ((sfamily = netlink_family_to_string(a->protocol)))
+ r = asprintf(p, "%s %u", sfamily, a->sockaddr.nl.nl_groups);
+ else
+ r = asprintf(p, "%i %u", a->protocol, a->sockaddr.nl.nl_groups);
+
+ if (r < 0)
+ return -ENOMEM;
+
+ return 0;
+ }
+
+ default:
+ return -EINVAL;
}
}
@@ -341,7 +408,7 @@ int socket_address_listen(
if (r < 0)
return r;
- fd = socket(socket_address_family(a), a->type | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
+ fd = socket(socket_address_family(a), a->type | SOCK_NONBLOCK | SOCK_CLOEXEC, a->protocol);
r = fd < 0 ? -errno : 0;
label_socket_clear();
@@ -356,14 +423,16 @@ int socket_address_listen(
goto fail;
}
- if (bind_to_device)
- if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bind_to_device, strlen(bind_to_device)+1) < 0)
- goto fail;
+ if (socket_address_family(a) == AF_INET || socket_address_family(a) == AF_INET6) {
+ if (bind_to_device)
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bind_to_device, strlen(bind_to_device)+1) < 0)
+ goto fail;
- if (free_bind) {
- one = 1;
- if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0)
- log_warning("IP_FREEBIND failed: %m");
+ if (free_bind) {
+ one = 1;
+ if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0)
+ log_warning("IP_FREEBIND failed: %m");
+ }
}
one = 1;
@@ -397,7 +466,7 @@ int socket_address_listen(
if (r < 0)
goto fail;
- if (a->type == SOCK_STREAM)
+ if (socket_address_can_accept(a))
if (listen(fd, backlog) < 0)
goto fail;
@@ -471,6 +540,16 @@ bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
break;
+ case AF_NETLINK:
+
+ if (a->protocol != b->protocol)
+ return false;
+
+ if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups)
+ return false;
+
+ break;
+
default:
/* Cannot compare, so we assume the addresses are different */
return false;
@@ -493,6 +572,18 @@ bool socket_address_is(const SocketAddress *a, const char *s, int type) {
return socket_address_equal(a, &b);
}
+bool socket_address_is_netlink(const SocketAddress *a, const char *s) {
+ struct SocketAddress b;
+
+ assert(a);
+ assert(s);
+
+ if (socket_address_parse_netlink(&b, s) < 0)
+ return false;
+
+ return socket_address_equal(a, &b);
+}
+
bool socket_address_needs_mount(const SocketAddress *a, const char *prefix) {
assert(a);
@@ -523,6 +614,28 @@ bool socket_ipv6_is_supported(void) {
return enabled;
}
+static const char* const netlink_family_table[] = {
+ [NETLINK_ROUTE] = "route",
+ [NETLINK_FIREWALL] = "firewall",
+ [NETLINK_INET_DIAG] = "inet-diag",
+ [NETLINK_NFLOG] = "nflog",
+ [NETLINK_XFRM] = "xfrm",
+ [NETLINK_SELINUX] = "selinux",
+ [NETLINK_ISCSI] = "iscsi",
+ [NETLINK_AUDIT] = "audit",
+ [NETLINK_FIB_LOOKUP] = "fib-lookup",
+ [NETLINK_CONNECTOR] = "connector",
+ [NETLINK_NETFILTER] = "netfilter",
+ [NETLINK_IP6_FW] = "ip6-fw",
+ [NETLINK_DNRTMSG] = "dnrtmsg",
+ [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
+ [NETLINK_GENERIC] = "generic",
+ [NETLINK_SCSITRANSPORT] = "scsitransport",
+ [NETLINK_ECRYPTFS] = "ecryptfs"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(netlink_family, int);
+
static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
[SOCKET_ADDRESS_DEFAULT] = "default",
[SOCKET_ADDRESS_BOTH] = "both",
diff --git a/src/socket-util.h b/src/socket-util.h
index 4743c37686..0e891ec2b2 100644
--- a/src/socket-util.h
+++ b/src/socket-util.h
@@ -26,6 +26,8 @@
#include <netinet/in.h>
#include <sys/un.h>
#include <net/if.h>
+#include <asm/types.h>
+#include <linux/netlink.h>
#include "macro.h"
#include "util.h"
@@ -35,6 +37,7 @@ union sockaddr_union {
struct sockaddr_in in4;
struct sockaddr_in6 in6;
struct sockaddr_un un;
+ struct sockaddr_nl nl;
struct sockaddr_storage storage;
};
@@ -47,6 +50,9 @@ typedef struct SocketAddress {
/* Socket type, i.e. SOCK_STREAM, SOCK_DGRAM, ... */
int type;
+
+ /* Socket protocol, IPPROTO_xxx, usually 0, except for netlink */
+ int protocol;
} SocketAddress;
typedef enum SocketAddressBindIPv6Only {
@@ -60,6 +66,7 @@ typedef enum SocketAddressBindIPv6Only {
#define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
int socket_address_parse(SocketAddress *a, const char *s);
+int socket_address_parse_netlink(SocketAddress *a, const char *s);
int socket_address_print(const SocketAddress *a, char **p);
int socket_address_verify(const SocketAddress *a);
@@ -77,6 +84,7 @@ int socket_address_listen(
int *ret);
bool socket_address_is(const SocketAddress *a, const char *s, int type);
+bool socket_address_is_netlink(const SocketAddress *a, const char *s);
bool socket_address_equal(const SocketAddress *a, const SocketAddress *b);
@@ -85,6 +93,9 @@ bool socket_address_needs_mount(const SocketAddress *a, const char *prefix);
const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b);
SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s);
+const char* netlink_family_to_string(int b);
+int netlink_family_from_string(const char *s);
+
bool socket_ipv6_is_supported(void);
#endif
diff --git a/src/socket.c b/src/socket.c
index beb328657f..ad67215c1f 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -249,7 +249,7 @@ static bool socket_needs_mount(Socket *s, const char *prefix) {
if (socket_address_needs_mount(&p->address, prefix))
return true;
} else {
- assert(p->type == SOCKET_FIFO);
+ assert(p->type == SOCKET_FIFO || p->type == SOCKET_SPECIAL);
if (path_startswith(p->path, prefix))
return true;
}
@@ -366,7 +366,10 @@ static int socket_load(Unit *u) {
return socket_verify(s);
}
-static const char* listen_lookup(int type) {
+static const char* listen_lookup(int family, int type) {
+
+ if (family == AF_NETLINK)
+ return "ListenNetlink";
if (type == SOCK_STREAM)
return "ListenStream";
@@ -477,9 +480,11 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
else
t = k;
- fprintf(f, "%s%s: %s\n", prefix, listen_lookup(p->address.type), t);
+ fprintf(f, "%s%s: %s\n", prefix, listen_lookup(socket_address_family(&p->address), p->address.type), t);
free(k);
- } else
+ } else if (p->type == SOCKET_SPECIAL)
+ fprintf(f, "%sListenSpecial: %s\n", prefix, p->path);
+ else
fprintf(f, "%sListenFIFO: %s\n", prefix, p->path);
}
@@ -684,7 +689,6 @@ static void socket_apply_fifo_options(Socket *s, int fd) {
log_warning("F_SETPIPE_SZ: %m");
}
-
static int fifo_address_create(
const char *path,
mode_t directory_mode,
@@ -712,7 +716,7 @@ static int fifo_address_create(
r = mkfifo(path, socket_mode);
umask(old_mask);
- if (r < 0) {
+ if (r < 0 && errno != EEXIST) {
r = -errno;
goto fail;
}
@@ -750,6 +754,42 @@ fail:
return r;
}
+static int special_address_create(
+ const char *path,
+ int *_fd) {
+
+ int fd = -1, r = 0;
+ struct stat st;
+
+ assert(path);
+ assert(_fd);
+
+ if ((fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW)) < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ if (fstat(fd, &st) < 0) {
+ r = -errno;
+ goto fail;
+ }
+
+ /* Check whether this is a /proc, /sys or /dev file or char device */
+ if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) {
+ r = -EEXIST;
+ goto fail;
+ }
+
+ *_fd = fd;
+ return 0;
+
+fail:
+ if (fd >= 0)
+ close_nointr_nofail(fd);
+
+ return r;
+}
+
static int socket_open_fds(Socket *s) {
SocketPort *p;
int r;
@@ -771,8 +811,10 @@ static int socket_open_fds(Socket *s) {
return r;
if (s->service && s->service->exec_command[SERVICE_EXEC_START])
- if ((r = label_get_socket_label_from_exe(s->service->exec_command[SERVICE_EXEC_START]->path, &label)) < 0)
- return r;
+ if ((r = label_get_socket_label_from_exe(s->service->exec_command[SERVICE_EXEC_START]->path, &label)) < 0) {
+ if (r != -EPERM)
+ return r;
+ }
know_label = true;
}
@@ -791,6 +833,13 @@ static int socket_open_fds(Socket *s) {
socket_apply_socket_options(s, p->fd);
+ } else if (p->type == SOCKET_SPECIAL) {
+
+ if ((r = special_address_create(
+ p->path,
+ &p->fd)) < 0)
+ goto rollback;
+
} else if (p->type == SOCKET_FIFO) {
if ((r = fifo_address_create(
@@ -1360,15 +1409,19 @@ static int socket_start(Unit *u) {
/* Cannot run this without the service being around */
if (s->service) {
- if (s->service->meta.load_state != UNIT_LOADED)
+ if (s->service->meta.load_state != UNIT_LOADED) {
+ log_error("Socket service %s not loaded, refusing.", s->service->meta.id);
return -ENOENT;
+ }
/* If the service is already active we cannot start the
* socket */
if (s->service->state != SERVICE_DEAD &&
s->service->state != SERVICE_FAILED &&
- s->service->state != SERVICE_AUTO_RESTART)
+ s->service->state != SERVICE_AUTO_RESTART) {
+ log_error("Socket service %s already active, refusing.", s->service->meta.id);
return -EBUSY;
+ }
#ifdef HAVE_SYSV_COMPAT
if (s->service->sysv_path) {
@@ -1447,9 +1500,14 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
if ((r = socket_address_print(&p->address, &t)) < 0)
return r;
- unit_serialize_item_format(u, f, "socket", "%i %i %s", copy, p->address.type, t);
+ if (socket_address_family(&p->address) == AF_NETLINK)
+ unit_serialize_item_format(u, f, "netlink", "%i %s", copy, t);
+ else
+ unit_serialize_item_format(u, f, "socket", "%i %i %s", copy, p->address.type, t);
free(t);
- } else {
+ } else if (p->type == SOCKET_SPECIAL)
+ unit_serialize_item_format(u, f, "special", "%i %s", copy, p->path);
+ else {
assert(p->type == SOCKET_FIFO);
unit_serialize_item_format(u, f, "fifo", "%i %s", copy, p->path);
}
@@ -1513,7 +1571,28 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
else {
LIST_FOREACH(port, p, s->ports)
- if (streq(p->path, value+skip))
+ if (p->type == SOCKET_FIFO &&
+ streq_ptr(p->path, value+skip))
+ break;
+
+ if (p) {
+ if (p->fd >= 0)
+ close_nointr_nofail(p->fd);
+ p->fd = fdset_remove(fds, fd);
+ }
+ }
+
+ } else if (streq(key, "special")) {
+ int fd, skip = 0;
+ SocketPort *p;
+
+ if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
+ log_debug("Failed to parse special value %s", value);
+ else {
+
+ LIST_FOREACH(port, p, s->ports)
+ if (p->type == SOCKET_SPECIAL &&
+ streq_ptr(p->path, value+skip))
break;
if (p) {
@@ -1542,6 +1621,25 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
}
}
+ } else if (streq(key, "netlink")) {
+ int fd, skip = 0;
+ SocketPort *p;
+
+ if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
+ log_debug("Failed to parse socket value %s", value);
+ else {
+
+ LIST_FOREACH(port, p, s->ports)
+ if (socket_address_is_netlink(&p->address, value+skip))
+ break;
+
+ if (p) {
+ if (p->fd >= 0)
+ close_nointr_nofail(p->fd);
+ p->fd = fdset_remove(fds, fd);
+ }
+ }
+
} else
log_debug("Unknown serialization key '%s'", key);
@@ -1581,7 +1679,7 @@ static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
log_debug("Incoming traffic on %s", u->meta.id);
if (events != EPOLLIN) {
- log_error("Got invalid poll event on socket.");
+ log_error("%s: Got invalid poll event (0x%x) on socket.", u->meta.id, events);
goto fail;
}
diff --git a/src/socket.h b/src/socket.h
index 9dd9f55fde..b83c34cf61 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -58,6 +58,7 @@ typedef enum SocketExecCommand {
typedef enum SocketType {
SOCKET_SOCKET,
SOCKET_FIFO,
+ SOCKET_SPECIAL,
_SOCKET_FIFO_MAX,
_SOCKET_FIFO_INVALID = -1
} SocketType;
diff --git a/src/strv.c b/src/strv.c
index c5f8df06da..71b77c9bbf 100644
--- a/src/strv.c
+++ b/src/strv.c
@@ -70,9 +70,10 @@ char **strv_copy(char **l) {
if (!(r = new(char*, strv_length(l)+1)))
return NULL;
- for (k = r; *l; k++, l++)
- if (!(*k = strdup(*l)))
- goto fail;
+ if (l)
+ for (k = r; *l; k++, l++)
+ if (!(*k = strdup(*l)))
+ goto fail;
*k = NULL;
return r;
@@ -357,7 +358,10 @@ char **strv_remove(char **l, const char *s) {
if (!l)
return NULL;
- /* Drops every occurrence of s in the string list */
+ assert(s);
+
+ /* Drops every occurrence of s in the string list, edits
+ * in-place. */
for (f = t = l; *f; f++) {
@@ -386,7 +390,12 @@ static int env_append(char **r, char ***k, char **a) {
for (; *a; a++) {
char **j;
- size_t n = strcspn(*a, "=") + 1;
+ size_t n;
+
+ n = strcspn(*a, "=");
+
+ if ((*a)[n] == '=')
+ n++;
for (j = r; j < *k; j++)
if (strncmp(*j, *a, n) == 0)
@@ -516,9 +525,38 @@ char **strv_env_delete(char **x, unsigned n_lists, ...) {
return r;
}
+char **strv_env_unset(char **l, const char *p) {
+
+ char **f, **t;
+
+ if (!l)
+ return NULL;
+
+ assert(p);
+
+ /* Drops every occurrence of the env var setting p in the
+ * string list. edits in-place. */
+
+ for (f = t = l; *f; f++) {
+
+ if (env_match(*f, p)) {
+ free(*f);
+ continue;
+ }
+
+ *(t++) = *f;
+ }
+
+ *t = NULL;
+ return l;
+}
+
char **strv_env_set(char **x, const char *p) {
char **k, **r;
+ char* m[2] = { (char*) p, NULL };
+
+ /* Overrides the env var setting of p, returns a new copy */
if (!(r = new(char*, strv_length(x)+2)))
return NULL;
@@ -527,7 +565,7 @@ char **strv_env_set(char **x, const char *p) {
if (env_append(r, &k, x) < 0)
goto fail;
- if (!(*(k++) = strdup(p)))
+ if (env_append(r, &k, m) < 0)
goto fail;
*k = NULL;
diff --git a/src/strv.h b/src/strv.h
index 064576ce1e..46436a52d9 100644
--- a/src/strv.h
+++ b/src/strv.h
@@ -59,6 +59,7 @@ char **strv_env_merge(unsigned n_lists, ...);
char **strv_env_delete(char **x, unsigned n_lists, ...);
char **strv_env_set(char **x, const char *p);
+char **strv_env_unset(char **l, const char *p);
char *strv_env_get_with_length(char **l, const char *name, size_t k);
char *strv_env_get(char **x, const char *n);
diff --git a/src/swap.c b/src/swap.c
index c32f60810c..ef001a98bf 100644
--- a/src/swap.c
+++ b/src/swap.c
@@ -90,6 +90,8 @@ static void swap_unset_proc_swaps(Swap *s) {
s->timer_watch.type = WATCH_INVALID;
s->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
+
+ s->meta.ignore_on_isolate = true;
}
static void swap_unwatch_control_pid(Swap *s) {
@@ -1339,7 +1341,6 @@ const UnitVTable swap_vtable = {
.no_alias = true,
.no_instances = true,
- .no_isolate = true,
.show_status = true,
.init = swap_init,
diff --git a/src/systemctl-bash-completion.sh b/src/systemctl-bash-completion.sh
index ae0ecb7b70..dc18ab6cce 100644
--- a/src/systemctl-bash-completion.sh
+++ b/src/systemctl-bash-completion.sh
@@ -81,7 +81,7 @@ _systemctl () {
[FAILED_UNITS]='reset-failed'
[STARTABLE_UNITS]='start restart reload-or-restart'
[STOPPABLE_UNITS]='stop kill try-restart condrestart'
- [ISOLATEBLE_UNITS]='isolate'
+ [ISOLATABLE_UNITS]='isolate'
[RELOADABLE_UNITS]='reload reload-or-try-restart force-reload'
[JOBS]='cancel'
[SNAPSHOTS]='delete'
diff --git a/src/systemctl.c b/src/systemctl.c
index 00db47f125..d1d73bfa01 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -1735,7 +1735,7 @@ static void exec_status_info_free(ExecStatusInfo *i) {
}
static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
- uint64_t start_timestamp, exit_timestamp;
+ uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
DBusMessageIter sub2, sub3;
const char*path;
unsigned n;
@@ -1789,7 +1789,9 @@ static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i)
if (!dbus_message_iter_next(&sub2) ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
+ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
@@ -2278,7 +2280,7 @@ static int print_property(const char *name, DBusMessageIter *iter) {
/* Yes, heuristics! But we can change this check
* should it turn out to not be sufficient */
- if (strstr(name, "Timestamp")) {
+ if (endswith(name, "Timestamp")) {
char timestamp[FORMAT_TIMESTAMP_MAX], *t;
if ((t = format_timestamp(timestamp, sizeof(timestamp), u)) || arg_all)
@@ -4079,7 +4081,7 @@ static int install_info_apply(const char *verb, LookupPaths *paths, InstallInfo
}
if (!f) {
-#if (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA)) && defined (HAVE_SYSV_COMPAT)
+#if (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA)) || defined(TARGET_MEEGO) && defined (HAVE_SYSV_COMPAT)
if (endswith(i->name, ".service")) {
char *sysv;
@@ -4150,6 +4152,15 @@ static int install_info_apply(const char *verb, LookupPaths *paths, InstallInfo
return -ENOENT;
}
+ /* Consider unit files stored in /lib and /usr always enabled
+ * if they have no [Install] data. */
+ if (streq(verb, "is-enabled") &&
+ strv_isempty(i->aliases) &&
+ strv_isempty(i->wanted_by) &&
+ (path_startswith(filename, "/lib") ||
+ path_startswith(filename, "/usr")))
+ return 1;
+
i->path = filename;
if ((r = config_parse(filename, f, NULL, items, true, i)) < 0) {
diff --git a/src/systemd-analyze b/src/systemd-analyze
index 5e3a087e9d..4f3e478e99 100755
--- a/src/systemd-analyze
+++ b/src/systemd-analyze
@@ -15,10 +15,10 @@ def acquire_time_data():
properties = dbus.Interface(bus.get_object('org.freedesktop.systemd1', i[6]), 'org.freedesktop.DBus.Properties')
- ixt = int(properties.Get('org.freedesktop.systemd1.Unit', 'InactiveExitTimestamp'))
- aet = int(properties.Get('org.freedesktop.systemd1.Unit', 'ActiveEnterTimestamp'))
- axt = int(properties.Get('org.freedesktop.systemd1.Unit', 'ActiveExitTimestamp'))
- iet = int(properties.Get('org.freedesktop.systemd1.Unit', 'InactiveEnterTimestamp'))
+ ixt = int(properties.Get('org.freedesktop.systemd1.Unit', 'InactiveExitTimestampMonotonic'))
+ aet = int(properties.Get('org.freedesktop.systemd1.Unit', 'ActiveEnterTimestampMonotonic'))
+ axt = int(properties.Get('org.freedesktop.systemd1.Unit', 'ActiveExitTimestampMonotonic'))
+ iet = int(properties.Get('org.freedesktop.systemd1.Unit', 'InactiveEnterTimestampMonotonic'))
l.append((str(i[0]), ixt, aet, axt, iet))
@@ -27,12 +27,14 @@ def acquire_time_data():
def acquire_start_time():
properties = dbus.Interface(bus.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1'), 'org.freedesktop.DBus.Properties')
- startup_time = int(properties.Get('org.freedesktop.systemd1.Manager', 'StartupTimestamp'))
- finish_time = int(properties.Get('org.freedesktop.systemd1.Manager', 'FinishTimestamp'))
+ initrd_time = int(properties.Get('org.freedesktop.systemd1.Manager', 'InitRDTimestampMonotonic'))
+ startup_time = int(properties.Get('org.freedesktop.systemd1.Manager', 'StartupTimestampMonotonic'))
+ finish_time = int(properties.Get('org.freedesktop.systemd1.Manager', 'FinishTimestampMonotonic'))
+ assert initrd_time <= startup_time
assert startup_time <= finish_time
- return startup_time, finish_time
+ return initrd_time, startup_time, finish_time
def draw_box(context, j, k, l, m, r = 0, g = 0, b = 0):
context.save()
@@ -63,7 +65,8 @@ def draw_text(context, x, y, text, size = 12, r = 0, g = 0, b = 0, vcenter = 0.5
context.restore()
def help():
- sys.stdout.write("""systemd-analyze blame
+ sys.stdout.write("""systemd-analyze time
+systemd-analyze blame
systemd-analyze plot
Process systemd profiling information
@@ -74,7 +77,24 @@ Process systemd profiling information
bus = dbus.SystemBus()
-if len(sys.argv) <= 1 or sys.argv[1] == 'blame':
+if len(sys.argv) <= 1 or sys.argv[1] == 'time':
+
+ initrd_time, start_time, finish_time = acquire_start_time()
+
+ if initrd_time > 0:
+ print "Startup finished in %lums (kernel) + %lums (initrd) + %lums (userspace) = %lums" % ( \
+ initrd_time/1000, \
+ (start_time - initrd_time)/1000, \
+ (finish_time - start_time)/1000, \
+ finish_time/1000)
+ else:
+ print "Startup finished in %lums (kernel) + %lums (userspace) = %lums" % ( \
+ start_time/1000, \
+ (finish_time - start_time)/1000, \
+ finish_time/1000)
+
+
+elif sys.argv[1] == 'blame':
data = acquire_time_data()
s = sorted(data, key = lambda i: i[2] - i[1], reverse = True)
@@ -92,7 +112,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == 'blame':
elif sys.argv[1] == 'plot':
import cairo
- start_time, finish_time = acquire_start_time()
+ initrd_time, start_time, finish_time = acquire_start_time()
data = acquire_time_data()
s = sorted(data, key = lambda i: i[1])
diff --git a/src/tmpfiles.c b/src/tmpfiles.c
index b21df95a73..2526d1e915 100644
--- a/src/tmpfiles.c
+++ b/src/tmpfiles.c
@@ -623,9 +623,39 @@ static void item_free(Item *i) {
free(i);
}
+static bool item_equal(Item *a, Item *b) {
+ assert(a);
+ assert(b);
+
+ if (!streq_ptr(a->path, b->path))
+ return false;
+
+ if (a->type != b->type)
+ return false;
+
+ if (a->uid_set != b->uid_set ||
+ (a->uid_set && a->uid != b->uid))
+ return false;
+
+ if (a->gid_set != b->gid_set ||
+ (a->gid_set && a->gid != b->gid))
+ return false;
+
+ if (a->mode_set != b->mode_set ||
+ (a->mode_set && a->mode != b->mode))
+ return false;
+
+ if (a->age_set != b->age_set ||
+ (a->age_set && a->age != b->age))
+ return false;
+
+ return true;
+}
+
static int parse_line(const char *fname, unsigned line, const char *buffer) {
- Item *i;
+ Item *i, *existing;
char *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
+ Hashmap *h;
int r;
assert(fname);
@@ -742,13 +772,19 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
i->age_set = true;
}
- if ((r = hashmap_put(needs_glob(i->type) ? globs : items, i->path, i)) < 0) {
- if (r == -EEXIST) {
+ h = needs_glob(i->type) ? globs : items;
+
+ if ((existing = hashmap_get(h, i->path))) {
+
+ /* Two identical items are fine */
+ if (!item_equal(existing, i))
log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
- r = 0;
- goto finish;
- }
+ r = 0;
+ goto finish;
+ }
+
+ if ((r = hashmap_put(h, i->path, i)) < 0) {
log_error("Failed to insert item %s: %s", i->path, strerror(-r));
goto finish;
}
diff --git a/src/tty-ask-password-agent.c b/src/tty-ask-password-agent.c
index dcf4b332b3..d7e1ebaef6 100644
--- a/src/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent.c
@@ -261,7 +261,6 @@ static int parse_password(const char *filename, char **wall) {
FILE *f;
int r;
- usec_t n;
assert(filename);
@@ -279,14 +278,22 @@ static int parse_password(const char *filename, char **wall) {
goto finish;
}
- if (!socket_name || not_after <= 0) {
+ if (!socket_name) {
log_error("Invalid password file %s", filename);
r = -EBADMSG;
goto finish;
}
- n = now(CLOCK_MONOTONIC);
- if (n > not_after) {
+ if (not_after > 0) {
+ if (now(CLOCK_MONOTONIC) > not_after) {
+ r = 0;
+ goto finish;
+ }
+ }
+
+ if (pid > 0 &&
+ kill(pid, 0) < 0 &&
+ errno == ESRCH) {
r = 0;
goto finish;
}
@@ -369,10 +376,15 @@ static int parse_password(const char *filename, char **wall) {
release_terminal();
}
- asprintf(&packet, "+%s", password);
- free(password);
+ packet_length = 1+strlen(password)+1;
+ if (!(packet = new(char, packet_length)))
+ r = -ENOMEM;
+ else {
+ packet[0] = '+';
+ strcpy(packet+1, password);
+ }
- packet_length = strlen(packet);
+ free(password);
}
if (r == -ETIME || r == -ENOENT) {
@@ -382,17 +394,10 @@ static int parse_password(const char *filename, char **wall) {
}
if (r < 0) {
-
log_error("Failed to query password: %s", strerror(-r));
goto finish;
}
- if (!packet) {
- log_error("Out of memory");
- r = -ENOMEM;
- goto finish;
- }
-
if ((socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) {
log_error("socket(): %m");
r = -errno;
diff --git a/src/unit.c b/src/unit.c
index e4345aeffe..aed25e4f21 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -368,7 +368,7 @@ void unit_free(Unit *u) {
u->meta.manager->n_in_gc_queue--;
}
- cgroup_bonding_free_list(u->meta.cgroup_bondings);
+ cgroup_bonding_free_list(u->meta.cgroup_bondings, u->meta.manager->n_serializing <= 0);
free(u->meta.description);
free(u->meta.fragment_path);
@@ -567,11 +567,8 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
/* If syslog or kernel logging is requested, make sure our own
* logging daemon is run first. */
- if ((r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_LOGGER_SOCKET, NULL, true)) < 0)
- return r;
-
if (u->meta.manager->running_as == MANAGER_SYSTEM)
- if ((r = unit_add_dependency_by_name(u, UNIT_REQUIRES, SPECIAL_LOGGER_SOCKET, NULL, true)) < 0)
+ if ((r = unit_add_two_dependencies_by_name(u, UNIT_REQUIRES, UNIT_AFTER, SPECIAL_LOGGER_SOCKET, NULL, true)) < 0)
return r;
return 0;
@@ -666,11 +663,15 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
"%s\tStopWhenUnneeded: %s\n"
"%s\tRefuseManualStart: %s\n"
"%s\tRefuseManualStop: %s\n"
- "%s\tDefaultDependencies: %s\n",
+ "%s\tDefaultDependencies: %s\n"
+ "%s\tOnFailureIsolate: %s\n"
+ "%s\tIgnoreOnIsolate: %s\n",
prefix, yes_no(u->meta.stop_when_unneeded),
prefix, yes_no(u->meta.refuse_manual_start),
prefix, yes_no(u->meta.refuse_manual_stop),
- prefix, yes_no(u->meta.default_dependencies));
+ prefix, yes_no(u->meta.default_dependencies),
+ prefix, yes_no(u->meta.on_failure_isolate),
+ prefix, yes_no(u->meta.ignore_on_isolate));
LIST_FOREACH(by_unit, b, u->meta.cgroup_bondings)
fprintf(f, "%s\tControlGroup: %s:%s\n",
@@ -815,6 +816,16 @@ int unit_load(Unit *u) {
if ((r = unit_add_default_dependencies(u)) < 0)
goto fail;
+ if (u->meta.on_failure_isolate &&
+ set_size(u->meta.dependencies[UNIT_ON_FAILURE]) > 1) {
+
+ log_error("More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.",
+ u->meta.id);
+
+ r = -EINVAL;
+ goto fail;
+ }
+
assert((u->meta.load_state != UNIT_MERGED) == !u->meta.merged_into);
unit_add_to_dbus_queue(unit_follow_merge(u));
@@ -1096,8 +1107,17 @@ void unit_trigger_on_failure(Unit *u) {
assert(u);
- SET_FOREACH(other, u->meta.dependencies[UNIT_ON_FAILURE], i)
- manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
+ if (set_size(u->meta.dependencies[UNIT_ON_FAILURE]) <= 0)
+ return;
+
+ log_info("Triggering OnFailure= dependencies of %s.", u->meta.id);
+
+ SET_FOREACH(other, u->meta.dependencies[UNIT_ON_FAILURE], i) {
+ int r;
+
+ if ((r = manager_add_job(u->meta.manager, JOB_START, other, u->meta.on_failure_isolate ? JOB_ISOLATE : JOB_REPLACE, true, NULL, NULL)) < 0)
+ log_error("Failed to enqueue OnFailure= job: %s", strerror(-r));
+ }
}
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) {
@@ -1858,6 +1878,9 @@ int unit_add_default_cgroups(Unit *u) {
/* Adds in the default cgroups, if they weren't specified
* otherwise. */
+ if (!u->meta.manager->cgroup_hierarchy)
+ return 0;
+
if ((r = unit_add_one_default_cgroup(u, NULL)) < 0)
return r;
@@ -2134,7 +2157,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
return 0;
for (;;) {
- char line[1024], *l, *v;
+ char line[LINE_MAX], *l, *v;
size_t k;
if (!fgets(line, sizeof(line), f)) {
diff --git a/src/unit.h b/src/unit.h
index 4245f3cf1c..43bbe67573 100644
--- a/src/unit.h
+++ b/src/unit.h
@@ -207,6 +207,12 @@ struct Meta {
/* Allow isolation requests */
bool allow_isolate;
+ /* Isolate OnFailure unit */
+ bool on_failure_isolate;
+
+ /* Ignore this unit when isolating */
+ bool ignore_on_isolate;
+
/* Did the last condition check suceed? */
bool condition_result;
@@ -364,9 +370,6 @@ struct UnitVTable {
/* Exclude from automatic gc */
bool no_gc:1;
- /* Exclude from stopping on isolation requests */
- bool no_isolate:1;
-
/* Show status updates on the console */
bool show_status:1;
};
diff --git a/src/util.c b/src/util.c
index 5daafdf7c2..5a076e6e34 100644
--- a/src/util.c
+++ b/src/util.c
@@ -50,6 +50,7 @@
#include <linux/kd.h>
#include <dlfcn.h>
#include <sys/wait.h>
+#include <sys/capability.h>
#include "macro.h"
#include "util.h"
@@ -452,14 +453,14 @@ char **split_path_and_make_absolute(const char *p) {
int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
int r;
FILE *f;
- char fn[132], line[256], *p;
+ char fn[PATH_MAX], line[LINE_MAX], *p;
long unsigned ppid;
- assert(pid >= 0);
+ assert(pid > 0);
assert(_ppid);
assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
- fn[sizeof(fn)-1] = 0;
+ char_array_0(fn);
if (!(f = fopen(fn, "r")))
return -errno;
@@ -495,6 +496,64 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
return 0;
}
+int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
+ int r;
+ FILE *f;
+ char fn[PATH_MAX], line[LINE_MAX], *p;
+
+ assert(pid > 0);
+ assert(st);
+
+ assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
+ char_array_0(fn);
+
+ if (!(f = fopen(fn, "r")))
+ return -errno;
+
+ if (!(fgets(line, sizeof(line), f))) {
+ r = -errno;
+ fclose(f);
+ return r;
+ }
+
+ fclose(f);
+
+ /* Let's skip the pid and comm fields. The latter is enclosed
+ * in () but does not escape any () in its value, so let's
+ * skip over it manually */
+
+ if (!(p = strrchr(line, ')')))
+ return -EIO;
+
+ p++;
+
+ if (sscanf(p, " "
+ "%*c " /* state */
+ "%*d " /* ppid */
+ "%*d " /* pgrp */
+ "%*d " /* session */
+ "%*d " /* tty_nr */
+ "%*d " /* tpgid */
+ "%*u " /* flags */
+ "%*u " /* minflt */
+ "%*u " /* cminflt */
+ "%*u " /* majflt */
+ "%*u " /* cmajflt */
+ "%*u " /* utime */
+ "%*u " /* stime */
+ "%*d " /* cutime */
+ "%*d " /* cstime */
+ "%*d " /* priority */
+ "%*d " /* nice */
+ "%*d " /* num_threads */
+ "%*d " /* itrealvalue */
+ "%llu " /* starttime */,
+ st) != 1)
+ return -EIO;
+
+ return 0;
+}
+
int write_one_line_file(const char *fn, const char *line) {
FILE *f;
int r;
@@ -549,6 +608,8 @@ int read_one_line_file(const char *fn, char **line) {
goto finish;
}
+ truncate_nl(c);
+
*line = c;
r = 0;
@@ -773,6 +834,29 @@ finish:
return r;
}
+int write_env_file(const char *fname, char **l) {
+
+ char **i;
+ FILE *f;
+ int r;
+
+ f = fopen(fname, "we");
+ if (!f)
+ return -errno;
+
+ STRV_FOREACH(i, l) {
+ fputs(*i, f);
+ fputc('\n', f);
+ }
+
+ fflush(f);
+
+ r = ferror(f) ? -errno : 0;
+ fclose(f);
+
+ return r;
+}
+
char *truncate_nl(char *s) {
assert(s);
@@ -796,7 +880,6 @@ int get_process_name(pid_t pid, char **name) {
if (r < 0)
return r;
- truncate_nl(*name);
return 0;
}
@@ -2063,7 +2146,7 @@ int chvt(int vt) {
int read_one_char(FILE *f, char *ret, bool *need_nl) {
struct termios old_termios, new_termios;
char c;
- char line[1024];
+ char line[LINE_MAX];
assert(f);
assert(ret);
@@ -2271,7 +2354,7 @@ int flush_fd(int fd) {
pollfd.events = POLLIN;
for (;;) {
- char buf[1024];
+ char buf[LINE_MAX];
ssize_t l;
int r;
@@ -2897,7 +2980,7 @@ int getttyname_harder(int fd, char **r) {
int get_ctty_devnr(dev_t *d) {
int k;
- char line[256], *p;
+ char line[LINE_MAX], *p;
unsigned long ttynr;
FILE *f;
@@ -2932,7 +3015,7 @@ int get_ctty_devnr(dev_t *d) {
int get_ctty(char **r, dev_t *_devnr) {
int k;
- char fn[128], *s, *b, *p;
+ char fn[PATH_MAX], *s, *b, *p;
dev_t devnr;
assert(r);
@@ -3198,8 +3281,7 @@ void status_welcome(void) {
if (r != -ENOENT)
log_warning("Failed to read /etc/system-release: %s", strerror(-r));
- } else
- truncate_nl(pretty_name);
+ }
}
if (!ansi_color && pretty_name) {
@@ -3220,8 +3302,7 @@ void status_welcome(void) {
if (r != -ENOENT)
log_warning("Failed to read /etc/SuSE-release: %s", strerror(-r));
- } else
- truncate_nl(pretty_name);
+ }
}
if (!ansi_color)
@@ -3234,8 +3315,7 @@ void status_welcome(void) {
if (r != -ENOENT)
log_warning("Failed to read /etc/gentoo-release: %s", strerror(-r));
- } else
- truncate_nl(pretty_name);
+ }
}
if (!ansi_color)
@@ -3248,8 +3328,7 @@ void status_welcome(void) {
if (r != -ENOENT)
log_warning("Failed to read /etc/altlinux-release: %s", strerror(-r));
- } else
- truncate_nl(pretty_name);
+ }
}
if (!ansi_color)
@@ -3266,7 +3345,6 @@ void status_welcome(void) {
if (r != -ENOENT)
log_warning("Failed to read /etc/debian_version: %s", strerror(-r));
} else {
- truncate_nl(version);
pretty_name = strappend("Debian ", version);
free(version);
@@ -3316,7 +3394,18 @@ void status_welcome(void) {
free(s);
}
}
+#elif defined(TARGET_MEEGO)
+ if (!pretty_name) {
+ if ((r = read_one_line_file("/etc/meego-release", &pretty_name)) < 0) {
+
+ if (r != -ENOENT)
+ log_warning("Failed to read /etc/meego-release: %s", strerror(-r));
+ }
+ }
+
+ if (!ansi_color)
+ const_color = "1;35"; /* Bright Magenta for MeeGo */
#endif
if (!pretty_name && !const_pretty)
@@ -3825,8 +3914,6 @@ const char *default_term_for_tty(const char *tty) {
* TERM */
if (streq(tty, "console"))
if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
- truncate_nl(active);
-
/* If multiple log outputs are configured the
* last one is what /dev/console points to */
if ((tty = strrchr(active, ' ')))
@@ -4236,6 +4323,76 @@ void parse_syslog_priority(char **p, int *priority) {
*p += k;
}
+int have_effective_cap(int value) {
+ cap_t cap;
+ cap_flag_value_t fv;
+ int r;
+
+ if (!(cap = cap_get_proc()))
+ return -errno;
+
+ if (cap_get_flag(cap, value, CAP_EFFECTIVE, &fv) < 0)
+ r = -errno;
+ else
+ r = fv == CAP_SET;
+
+ cap_free(cap);
+ return r;
+}
+
+char* strshorten(char *s, size_t l) {
+ assert(s);
+
+ if (l < strlen(s))
+ s[l] = 0;
+
+ return s;
+}
+
+static bool hostname_valid_char(char c) {
+ return
+ (c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') ||
+ c == '-' ||
+ c == '_' ||
+ c == '.';
+}
+
+bool hostname_is_valid(const char *s) {
+ const char *p;
+
+ if (isempty(s))
+ return false;
+
+ for (p = s; *p; p++)
+ if (!hostname_valid_char(*p))
+ return false;
+
+ if (p-s > HOST_NAME_MAX)
+ return false;
+
+ return true;
+}
+
+char* hostname_cleanup(char *s) {
+ char *p, *d;
+
+ for (p = s, d = s; *p; p++)
+ if ((*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9') ||
+ *p == '-' ||
+ *p == '_' ||
+ *p == '.')
+ *(d++) = *p;
+
+ *d = 0;
+
+ strshorten(s, HOST_NAME_MAX);
+ return s;
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",
diff --git a/src/util.h b/src/util.h
index ff38b35804..fcaeac4ab9 100644
--- a/src/util.h
+++ b/src/util.h
@@ -117,6 +117,10 @@ static inline bool is_path_absolute(const char *p) {
return *p == '/';
}
+static inline bool isempty(const char *p) {
+ return !p || !p[0];
+}
+
bool endswith(const char *s, const char *postfix);
bool startswith(const char *s, const char *prefix);
bool startswith_no_case(const char *s, const char *prefix);
@@ -192,6 +196,7 @@ char *split_quoted(const char *c, size_t *l, char **state);
char **split_path_and_make_absolute(const char *p);
pid_t get_parent_of_pid(pid_t pid, pid_t *ppid);
+int get_starttime_of_pid(pid_t pid, unsigned long long *st);
int write_one_line_file(const char *fn, const char *line);
int read_one_line_file(const char *fn, char **line);
@@ -199,6 +204,7 @@ int read_full_file(const char *fn, char **contents);
int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
int load_env_file(const char *fname, char ***l);
+int write_env_file(const char *fname, char **l);
char *strappend(const char *s, const char *suffix);
char *strnappend(const char *s, const char *suffix, size_t length);
@@ -396,6 +402,13 @@ bool plymouth_running(void);
void parse_syslog_priority(char **p, int *priority);
+int have_effective_cap(int value);
+
+bool hostname_is_valid(const char *s);
+char* hostname_cleanup(char *s);
+
+char* strshorten(char *s, size_t l);
+
#define NULSTR_FOREACH(i, l) \
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
diff --git a/src/vconsole-setup.c b/src/vconsole-setup.c
index 67fb7b6100..1be260bc2f 100644
--- a/src/vconsole-setup.c
+++ b/src/vconsole-setup.c
@@ -83,6 +83,12 @@ static int load_keymap(const char *vc, const char *map, const char *map_toggle,
int i = 0;
pid_t pid;
+ if (isempty(map)) {
+ /* An empty map means kernel map */
+ *_pid = 0;
+ return 0;
+ }
+
args[i++] = KBD_LOADKEYS;
args[i++] = "-q";
args[i++] = "-C";
@@ -111,6 +117,12 @@ static int load_font(const char *vc, const char *font, const char *map, const ch
int i = 0;
pid_t pid;
+ if (isempty(font)) {
+ /* An empty font means kernel font */
+ *_pid = 0;
+ return 0;
+ }
+
args[i++] = KBD_SETFONT;
args[i++] = "-C";
args[i++] = vc;
@@ -155,7 +167,7 @@ int main(int argc, char **argv) {
int r = EXIT_FAILURE;
pid_t font_pid = 0, keymap_pid = 0;
- log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
+ log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
log_open();
@@ -176,9 +188,19 @@ int main(int argc, char **argv) {
utf8 = is_locale_utf8();
+ vc_keymap = strdup("us");
+ vc_font = strdup(DEFAULT_FONT);
+
+ if (!vc_keymap || !vc_font) {
+ log_error("Failed to allocate strings.");
+ goto finish;
+ }
+
+ r = 0;
+
if (detect_container(NULL) <= 0)
if ((r = parse_env_file("/proc/cmdline", WHITESPACE,
-#ifdef TARGET_FEDORA
+#if defined(TARGET_FEDORA) || defined(TARGET_MEEGO)
"SYSFONT", &vc_font,
"KEYTABLE", &vc_keymap,
#endif
@@ -209,7 +231,7 @@ int main(int argc, char **argv) {
}
if (r <= 0) {
-#ifdef TARGET_FEDORA
+#if defined(TARGET_FEDORA) || defined(TARGET_MEEGO)
if ((r = parse_env_file("/etc/sysconfig/i18n", NEWLINE,
"SYSFONT", &vc_font,
"SYSFONTACM", &vc_font_map,
@@ -410,15 +432,7 @@ int main(int argc, char **argv) {
#endif
}
- if (!vc_keymap)
- vc_keymap = strdup("us");
- if (!vc_font)
- vc_font = strdup(DEFAULT_FONT);
-
- if (!vc_keymap || !vc_font) {
- log_error("Failed to allocate strings.");
- goto finish;
- }
+ r = EXIT_FAILURE;
if (!utf8)
disable_utf8(fd);
diff --git a/tmpfiles.d/systemd.conf b/tmpfiles.d/systemd.conf
index 2ab8e2bba5..5e8ed99916 100644
--- a/tmpfiles.d/systemd.conf
+++ b/tmpfiles.d/systemd.conf
@@ -21,3 +21,5 @@ d /var/cache/man - - - 30d
r /forcefsck
r /forcequotacheck
r /fastboot
+
+d /run/systemd/ask-password 0755 root root -
diff --git a/units/.gitignore b/units/.gitignore
index cbf9f255f0..fe23b12266 100644
--- a/units/.gitignore
+++ b/units/.gitignore
@@ -1,3 +1,4 @@
+systemd-hostnamed.service
console-shell.service
systemd-sysctl.service
systemd-ask-password-console.service
diff --git a/units/emergency.service b/units/emergency.service
index a97ec5e389..eff5261868 100644
--- a/units/emergency.service
+++ b/units/emergency.service
@@ -19,7 +19,7 @@ WorkingDirectory=/root
ExecStartPre=-/bin/plymouth quit
ExecStartPre=-/bin/echo 'Welcome to emergency mode. Use "systemctl default" or ^D to activate default mode.'
ExecStart=-/sbin/sulogin
-ExecStopPost=/bin/systemctl --fail default
+ExecStopPost=/bin/systemctl --fail --no-block default
StandardInput=tty-force
KillMode=process
diff --git a/units/fsck-root.service.in b/units/fsck-root.service.in
index 8f4adc48e0..7b3529db07 100644
--- a/units/fsck-root.service.in
+++ b/units/fsck-root.service.in
@@ -9,7 +9,7 @@
Description=File System Check on Root Device
DefaultDependencies=no
After=systemd-readahead-collect.service systemd-readahead-replay.service
-Before=local-fs.target shutdown.target remount-rootfs.service quotacheck.service
+Before=local-fs.target shutdown.target
# Dracut informs us with this flag file if the root fsck was already run
ConditionPathExists=!/run/initramfs/root-fsck
diff --git a/units/fsck@.service.in b/units/fsck@.service.in
index ad9ec3bcc9..e1f773639b 100644
--- a/units/fsck@.service.in
+++ b/units/fsck@.service.in
@@ -10,7 +10,7 @@ Description=File System Check on %f
DefaultDependencies=no
BindTo=%i.device
After=systemd-readahead-collect.service systemd-readahead-replay.service %i.device
-Before=basic.target shutdown.target
+Before=shutdown.target
[Service]
Type=oneshot
diff --git a/units/local-fs.target b/units/local-fs.target
index 52d0e68101..1886f7499d 100644
--- a/units/local-fs.target
+++ b/units/local-fs.target
@@ -9,3 +9,5 @@
[Unit]
Description=Local File Systems
+OnFailure=emergency.target
+OnFailureIsolate=yes
diff --git a/units/quotacheck.service.in b/units/quotacheck.service.in
index ed1ddc5589..27dcb1e4c6 100644
--- a/units/quotacheck.service.in
+++ b/units/quotacheck.service.in
@@ -8,7 +8,7 @@
[Unit]
Description=File System Quota Check
DefaultDependencies=no
-After=systemd-readahead-collect.service systemd-readahead-replay.service
+After=systemd-readahead-collect.service systemd-readahead-replay.service remount-rootfs.service
Before=local-fs.target shutdown.target
ConditionPathExists=/sbin/quotacheck
diff --git a/units/remount-rootfs.service b/units/remount-rootfs.service
index 31309015ca..e95023f03d 100644
--- a/units/remount-rootfs.service
+++ b/units/remount-rootfs.service
@@ -9,7 +9,7 @@
Description=Remount Root FS
DefaultDependencies=no
Conflicts=shutdown.target
-After=systemd-readahead-collect.service systemd-readahead-replay.service
+After=systemd-readahead-collect.service systemd-readahead-replay.service fsck-root.service
Before=local-fs.target shutdown.target
[Service]
diff --git a/units/rescue.service.m4 b/units/rescue.service.m4
index 241c75071f..d2fd582e86 100644
--- a/units/rescue.service.m4
+++ b/units/rescue.service.m4
@@ -25,8 +25,11 @@ ExecStart=-/bin/bash -c "exec ${SINGLE}"',
m4_ifdef(`TARGET_MANDRIVA',
`EnvironmentFile=/etc/sysconfig/init
ExecStart=-/bin/bash -c "exec ${SINGLE}"',
-`ExecStart=-/sbin/sulogin'))
-ExecStopPost=-/bin/systemctl --fail default
+`ExecStart=-/sbin/sulogin'
+m4_ifdef(`TARGET_MEEGO',
+`EnvironmentFile=/etc/sysconfig/init
+ExecStart=-/bin/bash -c "exec ${SINGLE}"',)))
+ExecStopPost=-/bin/systemctl --fail --no-block default
StandardInput=tty-force
KillMode=process
diff --git a/units/syslog.target b/units/syslog.target
index 8b1626ed55..825b26e7bf 100644
--- a/units/syslog.target
+++ b/units/syslog.target
@@ -12,3 +12,8 @@
[Unit]
Description=Syslog
+
+# Avoid that we conflict with shutdown.target, so that we can stay
+# until the very end and do not cancel shutdown.target if we should
+# hapen to be activated very late.
+DefaultDependencies=no
diff --git a/units/systemd-ask-password-console.path b/units/systemd-ask-password-console.path
index 4005a27734..b5acf943b4 100644
--- a/units/systemd-ask-password-console.path
+++ b/units/systemd-ask-password-console.path
@@ -13,3 +13,4 @@ Before=basic.target shutdown.target
[Path]
DirectoryNotEmpty=/run/systemd/ask-password
+MakeDirectory=yes
diff --git a/units/systemd-ask-password-plymouth.path b/units/systemd-ask-password-plymouth.path
index a2aec44122..6a96520921 100644
--- a/units/systemd-ask-password-plymouth.path
+++ b/units/systemd-ask-password-plymouth.path
@@ -13,3 +13,4 @@ Before=basic.target shutdown.target
[Path]
DirectoryNotEmpty=/run/systemd/ask-password
+MakeDirectory=yes
diff --git a/units/systemd-ask-password-wall.path b/units/systemd-ask-password-wall.path
index 7a883d5af8..050b73b2e1 100644
--- a/units/systemd-ask-password-wall.path
+++ b/units/systemd-ask-password-wall.path
@@ -13,3 +13,4 @@ Before=basic.target shutdown.target
[Path]
DirectoryNotEmpty=/run/systemd/ask-password
+MakeDirectory=yes
diff --git a/units/systemd-hostnamed.service.in b/units/systemd-hostnamed.service.in
new file mode 100644
index 0000000000..6efab1e25f
--- /dev/null
+++ b/units/systemd-hostnamed.service.in
@@ -0,0 +1,17 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# See systemd.special(7) for details
+
+[Unit]
+Description=Hostname Service
+
+[Service]
+ExecStart=@rootlibexecdir@/systemd-hostnamed
+Type=dbus
+BusName=org.freedesktop.hostname1
+CapabilityBoundingSet=CAP_SYS_ADMIN
diff --git a/units/systemd-kmsg-syslogd.service.in b/units/systemd-kmsg-syslogd.service.in
index b81e4a3069..b20889e5e5 100644
--- a/units/systemd-kmsg-syslogd.service.in
+++ b/units/systemd-kmsg-syslogd.service.in
@@ -14,4 +14,6 @@ DefaultDependencies=no
[Service]
ExecStart=@rootlibexecdir@/systemd-kmsg-syslogd
NotifyAccess=all
+StandardOutput=null
Sockets=syslog.socket
+CapabilityBoundingSet=CAP_DAC_OVERRIDE
diff --git a/units/systemd-logger.service.in b/units/systemd-logger.service.in
index f82db15ac1..5f7fe40939 100644
--- a/units/systemd-logger.service.in
+++ b/units/systemd-logger.service.in
@@ -10,9 +10,11 @@
[Unit]
Description=Stdio Syslog Bridge
DefaultDependencies=no
+Requires=syslog.socket
After=syslog.socket
[Service]
ExecStart=@rootlibexecdir@/systemd-logger
NotifyAccess=all
StandardOutput=null
+CapabilityBoundingSet=CAP_SYS_ADMIN CAP_SETUID CAP_SETGID
diff --git a/units/systemd-logger.socket b/units/systemd-logger.socket
index 389b507d24..7178cc8246 100644
--- a/units/systemd-logger.socket
+++ b/units/systemd-logger.socket
@@ -8,9 +8,14 @@
# See systemd.special(7) for details
[Unit]
-Description=Stream Logging Socket
+Description=Stdio Syslog Bridge Socket
DefaultDependencies=no
Before=sockets.target
+# Mount and swap units need this. If this socket unit is removed by an
+# isolate request the mount and and swap units would be removed too,
+# hence let's exclude this from isolate requests.
+IgnoreOnIsolate=yes
+
[Socket]
ListenStream=/run/systemd/logger
diff --git a/units/systemd-shutdownd.service.in b/units/systemd-shutdownd.service.in
index 2214cafab2..657365a451 100644
--- a/units/systemd-shutdownd.service.in
+++ b/units/systemd-shutdownd.service.in
@@ -8,7 +8,7 @@
# See systemd.special(7) for details
[Unit]
-Description=Delayed Shutdown Daemon
+Description=Delayed Shutdown Service
DefaultDependencies=no
[Service]
diff --git a/units/systemd-update-utmp-runlevel.service.in b/units/systemd-update-utmp-runlevel.service.in
index 865a1535de..614c759a63 100644
--- a/units/systemd-update-utmp-runlevel.service.in
+++ b/units/systemd-update-utmp-runlevel.service.in
@@ -8,7 +8,6 @@
[Unit]
Description=Notify Audit System and Update UTMP about System Runlevel Changes
DefaultDependencies=no
-Wants=local-fs.target sysinit.target
After=local-fs.target sysinit.target auditd.service runlevel1.target runlevel2.target runlevel3.target runlevel4.target runlevel5.target systemd-tmpfiles-setup.service
Before=poweroff.service reboot.service halt.service
diff --git a/units/systemd-update-utmp-shutdown.service.in b/units/systemd-update-utmp-shutdown.service.in
index c30d86d24c..e7c3c04a00 100644
--- a/units/systemd-update-utmp-shutdown.service.in
+++ b/units/systemd-update-utmp-shutdown.service.in
@@ -8,7 +8,6 @@
[Unit]
Description=Notify Audit System and Update UTMP about System Shutdown
DefaultDependencies=no
-Wants=local-fs.target sysinit.target
After=local-fs.target sysinit.target auditd.service systemd-update-utmp-runlevel.service
Before=poweroff.service reboot.service halt.service