summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile-man.am5
-rw-r--r--Makefile.am15
-rw-r--r--configure.ac70
-rw-r--r--hwdb/60-keyboard.hwdb8
-rw-r--r--hwdb/70-mouse.hwdb3
-rw-r--r--man/journalctl.xml2
-rw-r--r--man/systemd-journald.service.xml17
-rw-r--r--man/systemd.network.xml20
-rw-r--r--man/systemd.time.xml87
-rw-r--r--po/da.po1218
-rw-r--r--shell-completion/bash/systemd-run3
-rw-r--r--shell-completion/zsh/_udevadm2
-rw-r--r--src/basic/calendarspec.c35
-rw-r--r--src/basic/calendarspec.h1
-rw-r--r--src/basic/missing.h4
-rw-r--r--src/basic/time-util.c161
-rw-r--r--src/basic/time-util.h6
-rw-r--r--src/basic/util.c8
-rw-r--r--src/basic/util.h2
-rw-r--r--src/core/busname.c6
-rw-r--r--src/core/dbus-execute.c185
-rw-r--r--src/core/dbus-manager.c39
-rw-r--r--src/core/execute.c7
-rw-r--r--src/core/manager.c24
-rw-r--r--src/core/manager.h2
-rw-r--r--src/core/scope.c3
-rw-r--r--src/core/slice.c3
-rw-r--r--src/core/unit.c14
-rw-r--r--src/journal/compress.c221
-rw-r--r--src/journal/journalctl.c19
-rw-r--r--src/journal/journald-server.c27
-rw-r--r--src/journal/journald-stream.c7
-rw-r--r--src/journal/journald-stream.h4
-rw-r--r--src/journal/test-compress-benchmark.c36
-rw-r--r--src/journal/test-compress.c9
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c9
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c11
-rw-r--r--src/libsystemd-network/sd-icmp6-nd.c6
-rw-r--r--src/libsystemd-network/sd-ipv4ll.c39
-rw-r--r--src/libsystemd-network/test-ipv4ll.c11
-rw-r--r--src/libsystemd/sd-daemon/sd-daemon.c8
-rw-r--r--src/libsystemd/sd-netlink/netlink-internal.h6
-rw-r--r--src/libsystemd/sd-netlink/netlink-socket.c155
-rw-r--r--src/libsystemd/sd-netlink/rtnl-message.c60
-rw-r--r--src/libsystemd/sd-netlink/sd-netlink.c65
-rw-r--r--src/login/logind-dbus.c2
-rw-r--r--src/network/networkd-address-pool.c4
-rw-r--r--src/network/networkd-address.c262
-rw-r--r--src/network/networkd-address.h12
-rw-r--r--src/network/networkd-dhcp4.c32
-rw-r--r--src/network/networkd-dhcp6.c4
-rw-r--r--src/network/networkd-ipv4ll.c14
-rw-r--r--src/network/networkd-link.c263
-rw-r--r--src/network/networkd-link.h7
-rw-r--r--src/network/networkd-manager.c182
-rw-r--r--src/network/networkd-network.c8
-rw-r--r--src/network/networkd-route.c47
-rw-r--r--src/network/networkd-route.h4
-rw-r--r--src/network/networkd.h2
-rw-r--r--src/network/test-network.c13
-rw-r--r--src/nspawn/nspawn-mount.c6
-rw-r--r--src/rfkill/rfkill.c4
-rw-r--r--src/shared/bus-util.c77
-rw-r--r--src/shared/bus-util.h2
-rw-r--r--src/shared/fstab-util.c1
-rw-r--r--src/systemd/sd-ipv4ll.h1
-rw-r--r--src/systemd/sd-netlink.h4
-rw-r--r--src/test/test-calendarspec.c47
-rw-r--r--src/test/test-date.c41
-rw-r--r--src/tty-ask-password-agent/tty-ask-password-agent.c2
-rw-r--r--src/udev/.gitignore1
-rw-r--r--systemd-master/catalog/systemd.da.catalog261
-rw-r--r--units/.gitignore1
-rw-r--r--units/tmp.mount.m4 (renamed from units/tmp.mount)4
-rw-r--r--units/user/exit.target3
75 files changed, 2560 insertions, 1394 deletions
diff --git a/Makefile-man.am b/Makefile-man.am
index 1ff85d7d2c..56aa0fff1b 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -374,6 +374,7 @@ MANPAGES_ALIAS += \
man/systemd-hybrid-sleep.service.8 \
man/systemd-initctl.8 \
man/systemd-initctl.socket.8 \
+ man/systemd-journald-audit.socket.8 \
man/systemd-journald-dev-log.socket.8 \
man/systemd-journald.8 \
man/systemd-journald.socket.8 \
@@ -663,6 +664,7 @@ man/systemd-hibernate.service.8: man/systemd-suspend.service.8
man/systemd-hybrid-sleep.service.8: man/systemd-suspend.service.8
man/systemd-initctl.8: man/systemd-initctl.service.8
man/systemd-initctl.socket.8: man/systemd-initctl.service.8
+man/systemd-journald-audit.socket.8: man/systemd-journald.service.8
man/systemd-journald-dev-log.socket.8: man/systemd-journald.service.8
man/systemd-journald.8: man/systemd-journald.service.8
man/systemd-journald.socket.8: man/systemd-journald.service.8
@@ -1378,6 +1380,9 @@ man/systemd-initctl.html: man/systemd-initctl.service.html
man/systemd-initctl.socket.html: man/systemd-initctl.service.html
$(html-alias)
+man/systemd-journald-audit.socket.html: man/systemd-journald.service.html
+ $(html-alias)
+
man/systemd-journald-dev-log.socket.html: man/systemd-journald.service.html
$(html-alias)
diff --git a/Makefile.am b/Makefile.am
index 8646e55450..205f2a4d8d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -616,7 +616,8 @@ EXTRA_DIST += \
units/initrd-udevadm-cleanup-db.service.in \
units/initrd-switch-root.service.in \
units/systemd-nspawn@.service.in \
- units/systemd-update-done.service.in
+ units/systemd-update-done.service.in \
+ units/tmp.mount.m4
if HAVE_SYSV_COMPAT
nodist_systemunit_DATA += \
@@ -919,7 +920,6 @@ libbasic_la_CFLAGS = \
libbasic_la_LIBADD = \
$(SELINUX_LIBS) \
$(CAP_LIBS) \
- -ldl \
-lrt \
-lm
@@ -1229,7 +1229,7 @@ BUILT_SOURCES += \
$(gperf_gperf_m4_sources:-gperf.gperf.m4=-gperf-nulstr.c) \
$(gperf_gperf_sources:-gperf.gperf=-gperf.c) \
$(gperf_txt_sources:-list.txt=-from-name.h) \
- $(gperf_txt_sources:-list.txt=-to-name.h)
+ $(filter-out %keyboard-keys-to-name.h,$(gperf_txt_sources:-list.txt=-to-name.h))
CLEANFILES += \
$(gperf_txt_sources:-list.txt=-from-name.gperf)
@@ -3483,7 +3483,7 @@ noinst_LTLIBRARIES += \
src/udev/keyboard-keys-list.txt:
$(AM_V_at)$(MKDIR_P) $(dir $@)
- $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include linux/input.h - < /dev/null | $(AWK) '/^#define[ \t]+KEY_[^ ]+[ \t]+[0-9]/ { if ($$2 != "KEY_MAX") { print $$2 } }' | sed 's/^KEY_COFFEE$$/KEY_SCREENLOCK/' > $@
+ $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include linux/input.h - < /dev/null | $(AWK) '/^#define[ \t]+KEY_[^ ]+[ \t]+[0-9K]/ { if ($$2 != "KEY_MAX") { print $$2 } }' > $@
src/udev/keyboard-keys-from-name.gperf: src/udev/keyboard-keys-list.txt
$(AM_V_GEN)$(AWK) 'BEGIN{ print "struct key { const char* name; unsigned short id; };"; print "%null-strings"; print "%%";} { print tolower(substr($$1 ,5)) ", " $$1 }' < $< > $@
@@ -3491,9 +3491,6 @@ src/udev/keyboard-keys-from-name.gperf: src/udev/keyboard-keys-list.txt
src/udev/keyboard-keys-from-name.h: src/udev/keyboard-keys-from-name.gperf
$(AM_V_GPERF)$(GPERF) -L ANSI-C -t -N keyboard_lookup_key -H hash_key_name -p -C < $< > $@
-src/udev/keyboard-keys-to-name.h: src/udev/keyboard-keys-list.txt
- $(AM_V_GEN)$(AWK) 'BEGIN{ print "const char* const key_names[KEY_CNT] = { "} { print "[" $$1 "] = \"" $$1 "\"," } END{print "};"}' < $< > $@
-
gperf_txt_sources += \
src/udev/keyboard-keys-list.txt
@@ -3520,7 +3517,6 @@ libudev_core_la_SOURCES = \
nodist_libudev_core_la_SOURCES = \
src/udev/keyboard-keys-from-name.h \
- src/udev/keyboard-keys-to-name.h \
src/udev/net/link-config-gperf.c
gperf_gperf_sources += \
@@ -5148,7 +5144,8 @@ libnss_resolve_la_LDFLAGS = \
-Wl,--version-script=$(top_srcdir)/src/nss-resolve/nss-resolve.sym
libnss_resolve_la_LIBADD = \
- libshared.la
+ libshared.la \
+ -ldl
lib_LTLIBRARIES += \
libnss_resolve.la
diff --git a/configure.ac b/configure.ac
index 5e3cdd6d2b..c96b9fb1d9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -93,7 +93,6 @@ AC_PROG_GREP
AC_PROG_AWK
AC_PATH_PROG([M4], [m4])
-AC_PATH_PROG([XSLTPROC], [xsltproc])
AC_PATH_PROG([QUOTAON], [quotaon], [/usr/sbin/quotaon], [$PATH:/usr/sbin:/sbin])
AC_PATH_PROG([QUOTACHECK], [quotacheck], [/usr/sbin/quotacheck], [$PATH:/usr/sbin:/sbin])
@@ -282,7 +281,6 @@ AM_CONDITIONAL([HAVE_PYTHON], [test "x$have_python" = "xyes"])
# ------------------------------------------------------------------------------
-AC_SEARCH_LIBS([dlsym], [dl], [], [AC_MSG_ERROR([*** Dynamic linking loader library not found])])
AC_CHECK_HEADERS([sys/capability.h], [], [AC_MSG_ERROR([*** POSIX caps headers not found])])
AC_CHECK_HEADERS([linux/btrfs.h], [], [])
AC_CHECK_HEADERS([linux/memfd.h], [], [])
@@ -294,6 +292,7 @@ save_LIBS="$LIBS"
LIBS=
AC_SEARCH_LIBS([cap_init], [cap], [], [AC_MSG_ERROR([*** POSIX caps library not found])])
CAP_LIBS="$LIBS"
+LIBS="$save_LIBS"
AC_SUBST(CAP_LIBS)
AC_CHECK_FUNCS([memfd_create])
@@ -531,25 +530,27 @@ AC_SUBST(CERTIFICATEROOT)
# ------------------------------------------------------------------------------
have_xz=no
AC_ARG_ENABLE(xz, AS_HELP_STRING([--disable-xz], [Disable optional XZ support]))
-if test "x$enable_xz" != "xno"; then
+AS_IF([test "x$enable_xz" != "xno"], [
PKG_CHECK_MODULES(XZ, [ liblzma ],
- [AC_DEFINE(HAVE_XZ, 1, [Define if XZ is available]) have_xz=yes], have_xz=no)
- if test "x$have_xz" = xno -a "x$enable_xz" = xyes; then
- AC_MSG_ERROR([*** XZ support requested but libraries not found])
- fi
-fi
+ [AC_DEFINE(HAVE_XZ, 1, [Define if XZ is available])
+ have_xz=yes],
+ have_xz=no)
+ AS_IF([test "x$have_xz" = xno -a "x$enable_xz" = xyes],
+ [AC_MSG_ERROR([*** XZ support requested but libraries not found])])
+])
AM_CONDITIONAL(HAVE_XZ, [test "$have_xz" = "yes"])
# ------------------------------------------------------------------------------
have_zlib=no
AC_ARG_ENABLE(zlib, AS_HELP_STRING([--disable-zlib], [Disable optional ZLIB support]))
-if test "x$enable_zlib" != "xno"; then
+AS_IF([test "x$enable_zlib" != "xno"], [
PKG_CHECK_MODULES(ZLIB, [ zlib ],
- [AC_DEFINE(HAVE_ZLIB, 1, [Define if ZLIB is available]) have_zlib=yes], have_zlib=no)
- if test "x$have_zlib" = xno -a "x$enable_zlib" = xyes; then
- AC_MSG_ERROR([*** ZLIB support requested but libraries not found])
- fi
-fi
+ [AC_DEFINE(HAVE_ZLIB, 1, [Define if ZLIB is available])
+ have_zlib=yes],
+ have_zlib=no)
+ AS_IF([test "x$have_zlib" = xno -a "x$enable_zlib" = xyes],
+ [AC_MSG_ERROR([*** ZLIB support requested but libraries not found])])
+])
AM_CONDITIONAL(HAVE_ZLIB, [test "$have_zlib" = "yes"])
# ------------------------------------------------------------------------------
@@ -557,20 +558,24 @@ have_bzip2=no
AC_ARG_ENABLE(bzip2, AS_HELP_STRING([--enable-bzip2], [Disable optional BZIP2 support]))
AS_IF([test "x$enable_bzip2" != "xno"], [
AC_CHECK_HEADERS(bzlib.h,
- [AC_DEFINE(HAVE_BZIP2, 1, [Define in BZIP2 is available])
+ [AC_DEFINE(HAVE_BZIP2, 1, [Define if BZIP2 is available])
have_bzip2=yes],
- [AS_IF([test "x$have_bzip2" = xyes], [AC_MSG_ERROR([*** BZIP2 support requested but headers not found])])
- ])
+ [AS_IF([test "x$enable_bzip2" = xyes],
+ [AC_MSG_ERROR([*** BZIP2 support requested but headers not found])])]
+ )
])
AM_CONDITIONAL(HAVE_BZIP2, [test "$have_bzip2" = "yes"])
# ------------------------------------------------------------------------------
have_lz4=no
-AC_ARG_ENABLE(lz4, AS_HELP_STRING([--enable-lz4], [Enable optional LZ4 support]))
-AS_IF([test "x$enable_lz4" = "xyes"], [
- AC_CHECK_HEADERS(lz4.h,
- [AC_DEFINE(HAVE_LZ4, 1, [Define in LZ4 is available]) have_lz4=yes],
- [AC_MSG_ERROR([*** LZ4 support requested but headers not found])])
+AC_ARG_ENABLE(lz4, AS_HELP_STRING([--disable-lz4], [Disable optional LZ4 support]))
+AS_IF([test "x$enable_lz4" != "xno"], [
+ PKG_CHECK_MODULES(LZ4, [ liblz4 >= 125 ],
+ [AC_DEFINE(HAVE_LZ4, 1, [Define in LZ4 is available])
+ have_lz4=yes],
+ have_lz4=no)
+ AS_IF([test "x$have_lz4" = xno -a "x$enable_lz4" = xyes],
+ [AC_MSG_ERROR([*** LZ4 support requested but libraries not found])])
])
AM_CONDITIONAL(HAVE_LZ4, [test "$have_lz4" = "yes"])
@@ -791,14 +796,6 @@ if test "x${have_elfutils}" != xno ; then
AC_CHECK_LIB(
[dw],
- [dwfl_begin],
- [],
- [if test "x$have_elfutils" = xyes ; then
- AC_MSG_ERROR([*** ELFUTILS libs not found.])
- fi])
-
- AC_CHECK_LIB(
- [dw],
[dwfl_core_file_attach],
[have_elfutils=yes],
[if test "x$have_elfutils" = xyes ; then
@@ -1107,10 +1104,12 @@ AM_CONDITIONAL(ENABLE_POLKIT, [test "x$have_polkit" = "xyes"])
# ------------------------------------------------------------------------------
have_resolved=no
AC_ARG_ENABLE(resolved, AS_HELP_STRING([--disable-resolved], [disable resolve daemon]))
-if test "x$enable_resolved" != "xno"; then
+AS_IF([test "x$enable_resolved" != "xno"], [
+ AC_CHECK_LIB([dl], [dlsym], [true], [AC_MSG_ERROR([*** Dynamic linking loader library not found])])
+
have_resolved=yes
M4_DEFINES="$M4_DEFINES -DENABLE_RESOLVED"
-fi
+])
AM_CONDITIONAL(ENABLE_RESOLVED, [test "$have_resolved" = "yes"])
AC_ARG_WITH(dns-servers,
@@ -1286,7 +1285,12 @@ AM_CONDITIONAL(ENABLE_HWDB, [test x$enable_hwdb = xyes])
# ------------------------------------------------------------------------------
have_manpages=no
AC_ARG_ENABLE(manpages, AS_HELP_STRING([--disable-manpages], [disable manpages]))
-AS_IF([test "x$enable_manpages" != xno], [have_manpages=yes])
+AS_IF([test "x$enable_manpages" != xno], [
+ have_manpages=yes
+ AC_PATH_PROG([XSLTPROC], [xsltproc])
+ AS_IF([test -z "$XSLTPROC"],
+ AC_MSG_ERROR([*** xsltproc is required for man pages]))
+])
AM_CONDITIONAL(ENABLE_MANPAGES, [test "x$have_manpages" = "xyes"])
# ------------------------------------------------------------------------------
diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb
index 24db0d2ba6..9cb724acc0 100644
--- a/hwdb/60-keyboard.hwdb
+++ b/hwdb/60-keyboard.hwdb
@@ -494,6 +494,9 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPProBook445G1NotebookPC:pvr
# HP ProBook 450 G0
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPProBook450G0:pvr*
KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute
+# HP ProBook 6555b
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard:pnHPProBook6555b:*
+ KEYBOARD_KEY_b2=www # Earth
###########################################################
# IBM
@@ -648,11 +651,6 @@ evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*IdeaPad*Z370*:pvr*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*Lenovo*V480*:pvr*
KEYBOARD_KEY_f1=f21
-# Thinkpad Yoga 12 (2015)
-evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:pvrThinkPadS1Yoga12*
- KEYBOARD_KEY_d8=direction
- KEYBOARD_KEY_d9=direction
-
# enhanced USB keyboard
evdev:input:b0003v04B3p301B*
KEYBOARD_KEY_90001=prog1 # ThinkVantage
diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb
index 55e68a9138..2383d586a3 100644
--- a/hwdb/70-mouse.hwdb
+++ b/hwdb/70-mouse.hwdb
@@ -311,6 +311,9 @@ mouse:usb:v046dpc05a:name:Logitech USB Optical Mouse:
mouse:usb:v046dpc065:name:Logitech USB Laser Mouse:
# Logitech V500 Cordless Notebook Mouse
mouse:usb:v046dpc510:name:Logitech USB Receiver:
+# Logitech M560 Wireless Mouse
+mouse:usb:v046dp402d:name:Logitech M560:
+mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:402d:
MOUSE_DPI=1000@125
# Logitech V220 Cordless Optical Mouse
diff --git a/man/journalctl.xml b/man/journalctl.xml
index db3f166e65..91a5536ade 100644
--- a/man/journalctl.xml
+++ b/man/journalctl.xml
@@ -534,7 +534,9 @@
</varlistentry>
<varlistentry>
+ <term><option>-S</option></term>
<term><option>--since=</option></term>
+ <term><option>-U</option></term>
<term><option>--until=</option></term>
<listitem><para>Start showing entries on or newer than the
diff --git a/man/systemd-journald.service.xml b/man/systemd-journald.service.xml
index bd0082712e..8a72eedb16 100644
--- a/man/systemd-journald.service.xml
+++ b/man/systemd-journald.service.xml
@@ -46,6 +46,7 @@
<refname>systemd-journald.service</refname>
<refname>systemd-journald.socket</refname>
<refname>systemd-journald-dev-log.socket</refname>
+ <refname>systemd-journald-audit.socket</refname>
<refname>systemd-journald</refname>
<refpurpose>Journal service</refpurpose>
</refnamediv>
@@ -54,6 +55,7 @@
<para><filename>systemd-journald.service</filename></para>
<para><filename>systemd-journald.socket</filename></para>
<para><filename>systemd-journald-dev-log.socket</filename></para>
+ <para><filename>systemd-journald-audit.socket</filename></para>
<para><filename>/usr/lib/systemd/systemd-journald</filename></para>
</refsynopsisdiv>
@@ -230,7 +232,20 @@ systemd-tmpfiles --create --prefix /var/log/journal</programlisting>
<filename>/var/log/journal</filename> is not available, or
when <option>Storage=volatile</option> is set in the
<citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- configuration file. </para></listitem>
+ configuration file.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>/dev/kmsg</filename></term>
+ <term><filename>/dev/log</filename></term>
+ <term><filename>/run/systemd/journal/dev-log</filename></term>
+ <term><filename>/run/systemd/journal/socket</filename></term>
+ <term><filename>/run/systemd/journal/stdout</filename></term>
+
+ <listitem><para>Sockets and other paths that
+ <command>systemd-journald</command> will listen on that are
+ visible in the file system. In addition to those, journald can
+ listen for audit events using netlink.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index a27f2ff99e..1a33b77002 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -409,11 +409,21 @@
</varlistentry>
<varlistentry>
<term><varname>IPv6AcceptRouterAdvertisements=</varname></term>
- <listitem><para>Configures Accept Router Advertisements.
- This is enabled if local forwarding is disabled.
- Disabled if local forwarding is enabled.
- Takes a boolean. Defaults to unset.
- </para></listitem>
+ <listitem><para>Force the setting of <filename>accept_ra</filename>
+ (router advertisements) setting for the interface.
+ When unset, the kernel default is used, and router
+ advertisements are accepted only when local forwarding
+ is disabled for that interface.
+ Takes a boolean. If true, router advertisements are
+ accepted, when false, router advertisements are ignored,
+ independently of the local forwarding state.</para>
+
+ <para>See
+ <ulink url="https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt">ip-sysctl.txt</ulink>
+ in the kernel documentation, but note that systemd's
+ setting of <constant>1</constant> corresponds to
+ kernel's setting of <constant>2</constant>.</para>
+ </listitem>
</varlistentry>
<varlistentry>
<term><varname>Bridge=</varname></term>
diff --git a/man/systemd.time.xml b/man/systemd.time.xml
index 64358351d5..826e9fc5a5 100644
--- a/man/systemd.time.xml
+++ b/man/systemd.time.xml
@@ -117,10 +117,11 @@
<refsect1>
<title>Parsing Timestamps</title>
- <para>When parsing systemd will accept a similar timestamp syntax,
- but excluding any timezone specification (this limitation might be
- removed eventually). The weekday specification is optional, but
- when the weekday is specified it must either be in the abbreviated
+ <para>When parsing systemd will accept a similar syntax, but expects
+ no timezone specification, unless it is given as the literal string
+ "UTC". In this case the time is considered in UTC time, otherwise in
+ the local timezone. The weekday specification is optional, but when
+ the weekday is specified it must either be in the abbreviated
(<literal>Wed</literal>) or non-abbreviated
(<literal>Wednesday</literal>) English language form (case does
not matter), and is not subject to the locale choice of the user.
@@ -157,22 +158,29 @@
00:00.</para>
<para>Examples for valid timestamps and their normalized form
- (assuming the current time was 2012-11-23 18:15:22):</para>
+ (assuming the current time was 2012-11-23 18:15:22 and the timezone
+ was UTC+8, for example TZ=Asia/Shanghai):</para>
<programlisting>Fri 2012-11-23 11:12:13 → Fri 2012-11-23 11:12:13
2012-11-23 11:12:13 → Fri 2012-11-23 11:12:13
- 2012-11-23 → Fri 2012-11-23 00:00:00
- 12-11-23 → Fri 2012-11-23 00:00:00
- 11:12:13 → Fri 2012-11-23 11:12:13
- 11:12 → Fri 2012-11-23 11:12:00
- now → Fri 2012-11-23 18:15:22
- today → Fri 2012-11-23 00:00:00
- yesterday → Fri 2012-11-22 00:00:00
- tomorrow → Fri 2012-11-24 00:00:00
- +3h30min → Fri 2012-11-23 21:45:22
- -5s → Fri 2012-11-23 18:15:17
- 11min ago → Fri 2012-11-23 18:04:22
- @1395716396 → Tue 2014-03-25 03:59:56</programlisting>
+2012-11-23 11:12:13 UTC → Fri 2012-11-23 19:12:13
+ 2012-11-23 → Fri 2012-11-23 00:00:00
+ 12-11-23 → Fri 2012-11-23 00:00:00
+ 11:12:13 → Fri 2012-11-23 11:12:13
+ 11:12:13.9900009 → Fri 2012-11-23 11:12:13
+ format_timestamp_us: Fri 2012-11-23 11:12:13.990000
+ 11:12 → Fri 2012-11-23 11:12:00
+ now → Fri 2012-11-23 18:15:22
+ today → Fri 2012-11-23 00:00:00
+ today UTC → Fri 2012-11-23 16:00:00
+ yesterday → Fri 2012-11-22 00:00:00
+ tomorrow → Fri 2012-11-24 00:00:00
+ +3h30min → Fri 2012-11-23 21:45:22
+ +3h30min UTC → -EINVAL
+ -5s → Fri 2012-11-23 18:15:17
+ 11min ago → Fri 2012-11-23 18:04:22
+ 11min ago UTC → -EINVAL
+ @1395716396 → Tue 2014-03-25 03:59:56</programlisting>
<para>Note that timestamps printed by systemd will not be parsed
correctly by systemd, as the timezone specification is not
@@ -226,7 +234,8 @@
second component is not specified, <literal>:00</literal> is
assumed.</para>
- <para>Timezone names may not be specified.</para>
+ <para>A timezone specification is not expected, unless it is given
+ as the literal string "UTC", similarly to timestamps.</para>
<para>The special expressions
<literal>minutely</literal>,
@@ -242,7 +251,7 @@
<literal>*-*-01 00:00:00</literal>,
<literal>Mon *-*-* 00:00:00</literal>,
<literal>*-01-01 00:00:00</literal>,
- <literal>*-01,04,07,10-01 00:00:0</literal> and
+ <literal>*-01,04,07,10-01 00:00:00</literal> and
<literal>*-01,07-01 00:00:00</literal> respectively.
</para>
@@ -251,31 +260,33 @@
<programlisting> Sat,Thu,Mon-Wed,Sat-Sun → Mon-Thu,Sat,Sun *-*-* 00:00:00
Mon,Sun 12-*-* 2,1:23 → Mon,Sun 2012-*-* 01,02:23:00
- Wed *-1 → Wed *-*-01 00:00:00
- Wed-Wed,Wed *-1 → Wed *-*-01 00:00:00
- Wed, 17:48 → Wed *-*-* 17:48:00
+ Wed *-1 → Wed *-*-01 00:00:00
+ Wed-Wed,Wed *-1 → Wed *-*-01 00:00:00
+ Wed, 17:48 → Wed *-*-* 17:48:00
Wed-Sat,Tue 12-10-15 1:2:3 → Tue-Sat 2012-10-15 01:02:03
- *-*-7 0:0:0 → *-*-07 00:00:00
- 10-15 → *-10-15 00:00:00
+ *-*-7 0:0:0 → *-*-07 00:00:00
+ 10-15 → *-10-15 00:00:00
monday *-12-* 17:00 → Mon *-12-* 17:00:00
Mon,Fri *-*-3,1,2 *:30:45 → Mon,Fri *-*-01,02,03 *:30:45
12,14,13,12:20,10,30 → *-*-* 12,13,14:10,20,30:00
mon,fri *-1/2-1,3 *:30:45 → Mon,Fri *-01/2-01,03 *:30:45
- 03-05 08:05:40 → *-03-05 08:05:40
- 08:05:40 → *-*-* 08:05:40
- 05:40 → *-*-* 05:40:00
+ 03-05 08:05:40 → *-03-05 08:05:40
+ 08:05:40 → *-*-* 08:05:40
+ 05:40 → *-*-* 05:40:00
Sat,Sun 12-05 08:05:40 → Sat,Sun *-12-05 08:05:40
- Sat,Sun 08:05:40 → Sat,Sun *-*-* 08:05:40
- 2003-03-05 05:40 → 2003-03-05 05:40:00
- 2003-03-05 → 2003-03-05 00:00:00
- 03-05 → *-03-05 00:00:00
- hourly → *-*-* *:00:00
- daily → *-*-* 00:00:00
- monthly → *-*-01 00:00:00
- weekly → Mon *-*-* 00:00:00
- yearly → *-01-01 00:00:00
- annually → *-01-01 00:00:00
- *:2/3 → *-*-* *:02/3:00</programlisting>
+ Sat,Sun 08:05:40 → Sat,Sun *-*-* 08:05:40
+ 2003-03-05 05:40 → 2003-03-05 05:40:00
+ 2003-03-05 05:40 UTC → 2003-03-05 05:40:00 UTC
+ 2003-03-05 → 2003-03-05 00:00:00
+ 03-05 → *-03-05 00:00:00
+ hourly → *-*-* *:00:00
+ daily → *-*-* 00:00:00
+ daily UTC → *-*-* 00:00:00 UTC
+ monthly → *-*-01 00:00:00
+ weekly → Mon *-*-* 00:00:00
+ yearly → *-01-01 00:00:00
+ annually → *-01-01 00:00:00
+ *:2/3 → *-*-* *:02/3:00</programlisting>
<para>Calendar events are used by timer units, see
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>
diff --git a/po/da.po b/po/da.po
index 19bbb1eb78..a5be57940f 100644
--- a/po/da.po
+++ b/po/da.po
@@ -1,609 +1,609 @@
-# Danish translation for systemd.
-# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
-# This file is distributed under the same license as the systemd package.
-# Daniel Machon <dmachon.dev@gmail.com>, 2015.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: systemd master\n"
-"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
-"POT-Creation-Date: 2015-10-07 19:30+0000\n"
-"PO-Revision-Date: 2015-10-07 19:30+0200\n"
-"Last-Translator: Daniel Machon <dmachon.dev@gmail.com>\n"
-"Language-Team: danish\n"
-"Language: da\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
-msgid "Send passphrase back to system"
-msgstr "Send adgangssætning tilbage til systemet"
-
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
-msgid ""
-"Authentication is required to send the entered passphrase back to the system."
-msgstr ""
-"Autentificering er nødvendig for at sende adgangssætning tilbage til systemet."
-
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
-msgid "Manage system services or other units"
-msgstr "Håndtér system services eller andre enheder"
-
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
-msgid "Authentication is required to manage system services or other units."
-msgstr ""
-"Autentificering er nødvendig for at håndtere system services og andre enheder."
-
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
-msgid "Manage system service or unit files"
-msgstr "Håndtér system services eller enhedsfiler"
-
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
-msgid "Authentication is required to manage system service or unit files."
-msgstr ""
-"Autentificering er nødvendig for at håndtere system service eller enhedsfiler."
-
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
-msgid "Set or unset system and service manager environment variables"
-msgstr ""
-"Sæt eller fjern system- og service-forvalter miljøvariabler"
-
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
-msgid ""
-"Authentication is required to set or unset system and service manager "
-"environment variables."
-msgstr "Autentificering er nødvendig for at sætte eller fjerne system- "
-"og service-forvalter miljøvariabler."
-
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
-msgid "Reload the systemd state"
-msgstr "Genindlæs systemd tilstand"
-
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
-msgid "Authentication is required to reload the systemd state."
-msgstr "Autentificering er nødvendig for at genindlæse systemd tilstanden."
-
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
-msgid "Set host name"
-msgstr "Sæt værtsnavn"
-
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
-msgid "Authentication is required to set the local host name."
-msgstr "Autentificering er nødvendig for at sætte værtsnavn."
-
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
-msgid "Set static host name"
-msgstr "Sæt statisk værstnavn"
-
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
-msgid ""
-"Authentication is required to set the statically configured local host name, "
-"as well as the pretty host name."
-msgstr ""
-"Autentificering er nødvendig for at sætte det statisk konfigurerede lokale "
-"værtsnavn, lige så vel som det pæne værtsnavn."
-
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
-msgid "Set machine information"
-msgstr "Sæt maskininformation."
-
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
-msgid "Authentication is required to set local machine information."
-msgstr "Autentificering er nødvendig for at sætte lokal maskininformation."
-
-#: ../src/import/org.freedesktop.import1.policy.in.h:1
-msgid "Import a VM or container image"
-msgstr "Importér en VM eller container billede"
-
-#: ../src/import/org.freedesktop.import1.policy.in.h:2
-msgid "Authentication is required to import a VM or container image"
-msgstr ""
-"Autentificering er nødvendig for at importére en VM eller "
-"container billeder."
-
-#: ../src/import/org.freedesktop.import1.policy.in.h:3
-msgid "Export a VM or container image"
-msgstr "Exportér en VM eller container billede"
-
-#: ../src/import/org.freedesktop.import1.policy.in.h:4
-msgid "Authentication is required to export a VM or container image"
-msgstr "Autentificering er nødvendig for at exportére en VM eller container billede"
-
-#: ../src/import/org.freedesktop.import1.policy.in.h:5
-msgid "Download a VM or container image"
-msgstr "Hent en VM eller container billede"
-
-#: ../src/import/org.freedesktop.import1.policy.in.h:6
-msgid "Authentication is required to download a VM or container image"
-msgstr "Autentificering er nødvendig for at hente en VM eller container billede"
-
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
-msgid "Set system locale"
-msgstr "Sæt sprogindstillinger for systemet"
-
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
-msgid "Authentication is required to set the system locale."
-msgstr ""
-"Autentificering er nødvendig for at sætte sprogindstillinger "
-"for systemet."
-
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
-msgid "Set system keyboard settings"
-msgstr "Sæt tastaturindstillinger for systemet."
-
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
-msgid "Authentication is required to set the system keyboard settings."
-msgstr ""
-"Autentificering er nødvendig for at sætte tastaturindstillinger "
-"for systemet."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:1
-msgid "Allow applications to inhibit system shutdown"
-msgstr "Tillad applikationer at hæmme system nedlukning"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:2
-msgid ""
-"Authentication is required for an application to inhibit system shutdown."
-msgstr ""
-"Autentificering er nødvendig for at en applikation kan hæmme "
-"system nedlukning."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:3
-msgid "Allow applications to delay system shutdown"
-msgstr "Tillad applikationer at forsinke system nedlukning"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:4
-msgid "Authentication is required for an application to delay system shutdown."
-msgstr ""
-"Autentificering er nødvendig for at en applikation kan forsinke "
-"system nedlukning."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:5
-msgid "Allow applications to inhibit system sleep"
-msgstr "Tillad applikationer at hæmme system dvale"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:6
-msgid "Authentication is required for an application to inhibit system sleep"
-msgstr "Autentificering er nødvendig for at en applikation kan hæmme system dvale"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:7
-msgid "Allow applications to delay system sleep"
-msgstr "Tillad applikationer at forsinke system dvale"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:8
-msgid "Authentication is required for an application to delay system sleep."
-msgstr ""
-"Autentificering er nødvendig for at en applikation kan forsinke system "
-"dvale."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:9
-msgid "Allow applications to inhibit automatic system suspend"
-msgstr "Tillad applikationer at hæmme automatisk system standby"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:10
-msgid ""
-"Authentication is required for an application to inhibit automatic system "
-"suspend."
-msgstr ""
-"Autentificering er nødvendig for at en applikation kan hæmme automatisk "
-"system standby."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:11
-msgid "Allow applications to inhibit system handling of the power key"
-msgstr "Tillad applikationer at hæmme systemhåndtering af tænd/sluk-knappen"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:12
-msgid ""
-"Authentication is required for an application to inhibit system handling of "
-"the power key."
-msgstr ""
-"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering "
-"af tænd/sluk-knappen."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:13
-msgid "Allow applications to inhibit system handling of the suspend key"
-msgstr "Tillad applikationer at hæmme systemhåndtering af standby-knappen"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:14
-msgid ""
-"Authentication is required for an application to inhibit system handling of "
-"the suspend key."
-msgstr ""
-"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering "
-"af standby-knappen."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:15
-msgid "Allow applications to inhibit system handling of the hibernate key"
-msgstr "Tillad applikationer at hæmme systemhåndtering af dvale-knappen"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:16
-msgid ""
-"Authentication is required for an application to inhibit system handling of "
-"the hibernate key."
-msgstr ""
-"Autentificering er nødvendig for at en applikation kan hæmme "
-"systemhåndtering af dvale-knappen."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:17
-msgid "Allow applications to inhibit system handling of the lid switch"
-msgstr ""
-"Tillad applikationer at hæmme systemhåndtering af skærmlukning"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:18
-msgid ""
-"Authentication is required for an application to inhibit system handling of "
-"the lid switch."
-msgstr ""
-"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering "
-"af skærmlukning."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:19
-msgid "Allow non-logged-in users to run programs"
-msgstr "Tillad brugere der ikke er logget ind, at køre programmer"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
-msgid "Authentication is required to run programs as a non-logged-in user."
-msgstr ""
-"Autentificering er nødvendig for at brugere, som ikke er logget ind, kan "
-"køre programmer."
-
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
-msgid "Allow attaching devices to seats"
-msgstr "Tillad at montere af enheder til arbejdsstationer"
-
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
-msgid "Authentication is required for attaching a device to a seat."
-msgstr ""
-"Autentificering er nødvendig for at montere en enhed til en "
-"arbejdsstation."
-
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
-msgid "Flush device to seat attachments"
-msgstr "Nulstil enhed monteret til en arbejdsstation"
-
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
-msgid ""
-"Authentication is required for resetting how devices are attached to seats."
-msgstr ""
-"Autentificering er nødvendig for at nulstille måden enheder er monteret "
-"arbejdsstationer."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
-msgid "Power off the system"
-msgstr "Sluk for systemet"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
-msgid "Authentication is required for powering off the system."
-msgstr "Autentificering er nødvendig for at slukke systemet"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
-msgid "Power off the system while other users are logged in"
-msgstr "Sluk systemet mens andre brugere er logget på"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
-msgid ""
-"Authentication is required for powering off the system while other users are "
-"logged in."
-msgstr ""
-"Autentificering er nødvendig for at slukke systemet mens andre brugere "
-"er logget på."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
-msgid "Power off the system while an application asked to inhibit it"
-msgstr ""
-"Sluk for systemet mens en applikation har forespurgt at hæmme det"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
-msgid ""
-"Authentication is required for powering off the system while an application "
-"asked to inhibit it."
-msgstr ""
-"Autentificering er nødvendig for at slukke systemet mens en applikation har "
-"forespurgt at hæmme det."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
-msgid "Reboot the system"
-msgstr "Genstart systemet"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
-msgid "Authentication is required for rebooting the system."
-msgstr "Autentificering er nødvendig for at genstarte systemet."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
-msgid "Reboot the system while other users are logged in"
-msgstr "Genstart systemet mens andre brugere er logget ind"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
-msgid ""
-"Authentication is required for rebooting the system while other users are "
-"logged in."
-msgstr ""
-"Autentificering er nødvendig for at genstarte systemet mens andre brugere "
-"er logget ind."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
-msgid "Reboot the system while an application asked to inhibit it"
-msgstr ""
-"Genstart systemet mens en applikation har forespurgt at hæmme det"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
-msgid ""
-"Authentication is required for rebooting the system while an application "
-"asked to inhibit it."
-msgstr ""
-"Autentificering er nødvendig for at genstarte systemet mens en applikation "
-"har forespurgt at hæmme det."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
-msgid "Suspend the system"
-msgstr "Sæt systemet på standby"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
-msgid "Authentication is required for suspending the system."
-msgstr "Autentificering er nødvendig for at sætte systemet på standby"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
-msgid "Suspend the system while other users are logged in"
-msgstr "Sæt systemet på standby mens andre brugere er logget på"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
-msgid ""
-"Authentication is required for suspending the system while other users are "
-"logged in."
-msgstr ""
-"Autentificering er nødvendig for at sætte systemet på standby, mens andre "
-"brugere er logget på."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
-msgid "Suspend the system while an application asked to inhibit it"
-msgstr ""
-"Sæt systemet på standby mens en applikation har forespurgt at hæmme"
-"det"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
-msgid ""
-"Authentication is required for suspending the system while an application "
-"asked to inhibit it."
-msgstr ""
-"Autentificering er nødvendig for at sætte systemet på standby, mens en "
-"applikation har forespurgt at hæmme det."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
-msgid "Hibernate the system"
-msgstr "Sæt systemet i dvale"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
-msgid "Authentication is required for hibernating the system."
-msgstr ""
-"Autentificering er nødvendig for at sætte systemet i dvale-tilstand."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
-msgid "Hibernate the system while other users are logged in"
-msgstr ""
-"Sæt systemet i dvale-tilstand mens andre brugere er logget på"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
-msgid ""
-"Authentication is required for hibernating the system while other users are "
-"logged in."
-msgstr ""
-"Autentificering er nødvendig for at sætte systemet i dvale-tilstand, mens "
-"andre brugere er logget på."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
-msgid "Hibernate the system while an application asked to inhibit it"
-msgstr "Sæt systemet i dvale-tilstand mens en applikation har forespurgt at "
-"hæmme det"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
-msgid ""
-"Authentication is required for hibernating the system while an application "
-"asked to inhibit it."
-msgstr ""
-"Autentificering er nødvendig for at sætte systemet i dvale tilstand, mens "
-"en applikation har forespurgt at hæmme det."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
-msgid "Manage active sessions, users and seats"
-msgstr "Håndtér aktive sessioner, brugere og arbejdsstationer"
-
-# www.freedesktop.org/wiki/Software/systemd/multiseat/
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
-msgid ""
-"Authentication is required for managing active sessions, users and seats."
-msgstr ""
-"Autentificering er nødvendig for at håndtere aktive sessioner, brugere "
-"og arbejdsstationer."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
-msgid "Lock or unlock active sessions"
-msgstr "Lås eller oplås aktive sessioner"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
-msgid "Authentication is required to lock or unlock active sessions."
-msgstr ""
-"Autentificering er nødvendig for at låse eller oplåse aktive sessioner."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
-msgid "Allow indication to the firmware to boot to setup interface"
-msgstr "Tillad meddelelse til firmwaren om at starte op i opsætningsgrænseflade"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
-msgid ""
-"Authentication is required to indicate to the firmware to boot to setup "
-"interface."
-msgstr "Autentificering er nødvendig for at meddele firmwaren om at starte "
-"op i opsætningsgrænseflade."
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
-msgid "Set a wall message"
-msgstr "Sæt broadcast-besked"
-
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
-msgid "Authentication is required to set a wall message"
-msgstr "Autentificering er nødvendig for at sætte en broadcast-besked"
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
-msgid "Log into a local container"
-msgstr "Log på en lokal container"
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
-msgid "Authentication is required to log into a local container."
-msgstr "Autentificering er nødvendig for at logge på en lokal container."
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
-msgid "Log into the local host"
-msgstr "Log på den lokale vært"
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
-msgid "Authentication is required to log into the local host."
-msgstr "Auitentificering er nødvendig for at logge på den lokale vært."
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
-msgid "Acquire a shell in a local container"
-msgstr "Anskaf en shell i en lokal container"
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
-msgid "Authentication is required to acquire a shell in a local container."
-msgstr ""
-"Autentificering er nødvendig for at anskaffe en shell i en lokal "
-"container."
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
-msgid "Acquire a shell on the local host"
-msgstr "Anskaf en shell på den lokale vært"
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
-msgid "Authentication is required to acquire a shell on the local host."
-msgstr ""
-"Autentificering er nødvendig for at anskaffe en shell på den lokale vært."
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
-msgid "Acquire a pseudo TTY in a local container"
-msgstr "Anskaf en pseudo-TTY i en lokal container"
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
-msgid ""
-"Authentication is required to acquire a pseudo TTY in a local container."
-msgstr ""
-"Autentificering er nødvendig for at anskaffe en pseudo-TTY i en lokal "
-"container."
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
-msgid "Acquire a pseudo TTY on the local host"
-msgstr "Anskaf en pseudo-TTY på den lokale vært"
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
-msgid "Authentication is required to acquire a pseudo TTY on the local host."
-msgstr ""
-"Autentificering er nødvendig for at anskaffe en pseudo-TTY på den "
-"lokale vært."
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
-msgid "Manage local virtual machines and containers"
-msgstr "Håndtér lokale virtuelle maskiner og containere"
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
-msgid ""
-"Authentication is required to manage local virtual machines and containers."
-msgstr ""
-"Autentificering er nødvendig for at håndtere lokale virtuelle maskiner og "
-"containere."
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
-msgid "Manage local virtual machine and container images"
-msgstr "Håndtér lokal virtuel maskine- og container billeder"
-
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
-msgid ""
-"Authentication is required to manage local virtual machine and container "
-"images."
-msgstr ""
-"Autentificering er nødvendig for at håndtere lokal virtuel maskine- og "
-"container billeder."
-
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
-msgid "Set system time"
-msgstr "Sæt tiden for systemet"
-
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
-msgid "Authentication is required to set the system time."
-msgstr "Autentificering er nødvendig for at sætte tiden for systemet."
-
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
-msgid "Set system timezone"
-msgstr "Sæt tidszone for systemet"
-
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
-msgid "Authentication is required to set the system timezone."
-msgstr "Autentificering er nødvendig for at sætte tidszonen for systemet."
-
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
-msgid "Set RTC to local timezone or UTC"
-msgstr "Sæt RTC til lokal tidszone eller UTC"
-
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
-msgid ""
-"Authentication is required to control whether the RTC stores the local or "
-"UTC time."
-msgstr ""
-"Autentificering er nødvendig for at kontrollere hvorvidt RTC'en gemmer "
-"den lokale tid eller UTC tid."
-
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
-msgid "Turn network time synchronization on or off"
-msgstr "Slå synkronisering af netværkstid til eller fra"
-
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
-msgid ""
-"Authentication is required to control whether network time synchronization "
-"shall be enabled."
-msgstr ""
-"Autentificering er nødvendig for at kontrollere hvorvidt synkronisering af "
-"netværkstid skal aktiveres"
-
-#: ../src/core/dbus-unit.c:428
-msgid "Authentication is required to start '$(unit)'."
-msgstr "Autentificering er nødvendig for at starte '$(unit)'."
-
-#: ../src/core/dbus-unit.c:429
-msgid "Authentication is required to stop '$(unit)'."
-msgstr "Autentificering er nødvendig for at stoppe '$(unit)'."
-
-#: ../src/core/dbus-unit.c:430
-msgid "Authentication is required to reload '$(unit)'."
-msgstr "Autentificering er nødvendig for at genindlæse '$(unit)'."
-
-#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
-msgid "Authentication is required to restart '$(unit)'."
-msgstr "Autentificering at nødvendig for at genstarte '$(unit)'."
-
-#: ../src/core/dbus-unit.c:535
-msgid "Authentication is required to kill '$(unit)'."
-msgstr "Autentificering er nødvendig for at eliminere '$(unit)'."
-
-#: ../src/core/dbus-unit.c:565
-msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
-msgstr ""
-"Autentificering er nødvendig for at nulstille \"fejl\" tilstanden på '$(unit)'."
-
-#: ../src/core/dbus-unit.c:597
-msgid "Authentication is required to set properties on '$(unit)'."
-msgstr ""
-"Autentificering er nødvendig for at sætte egenskaber på '$(unit)'."
-
-#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
-#~ msgstr ""
-#~ "Tryk Ctrl-C for at annulere alle igangværende kontrolleringer af "
-#~ "filsystemet"
-
-#~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
-#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
-#~ msgstr[0] "Igangværende kontrollering på %d disk (%3.1f%% færdig)"
-#~ msgstr[1] "Igangværende kontrollering på %d diske (%3.1f%% færdig)"
+# Danish translation for systemd.
+# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
+# This file is distributed under the same license as the systemd package.
+# Daniel Machon <dmachon.dev@gmail.com>, 2015.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: systemd master\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2015-10-07 19:30+0000\n"
+"PO-Revision-Date: 2015-10-07 19:30+0200\n"
+"Last-Translator: Daniel Machon <dmachon.dev@gmail.com>\n"
+"Language-Team: danish\n"
+"Language: da\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
+msgid "Send passphrase back to system"
+msgstr "Send adgangssætning tilbage til systemet"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
+msgid ""
+"Authentication is required to send the entered passphrase back to the system."
+msgstr ""
+"Autentificering er nødvendig for at sende adgangssætning tilbage til systemet."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
+msgid "Manage system services or other units"
+msgstr "Håndtér system services eller andre enheder"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
+msgid "Authentication is required to manage system services or other units."
+msgstr ""
+"Autentificering er nødvendig for at håndtere system services og andre enheder."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
+msgid "Manage system service or unit files"
+msgstr "Håndtér system services eller enhedsfiler"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
+msgid "Authentication is required to manage system service or unit files."
+msgstr ""
+"Autentificering er nødvendig for at håndtere system service eller enhedsfiler."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
+msgid "Set or unset system and service manager environment variables"
+msgstr ""
+"Sæt eller fjern system- og service-forvalter miljøvariabler"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
+msgid ""
+"Authentication is required to set or unset system and service manager "
+"environment variables."
+msgstr "Autentificering er nødvendig for at sætte eller fjerne system- "
+"og service-forvalter miljøvariabler."
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
+msgid "Reload the systemd state"
+msgstr "Genindlæs systemd tilstand"
+
+#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
+msgid "Authentication is required to reload the systemd state."
+msgstr "Autentificering er nødvendig for at genindlæse systemd tilstanden."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
+msgid "Set host name"
+msgstr "Sæt værtsnavn"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
+msgid "Authentication is required to set the local host name."
+msgstr "Autentificering er nødvendig for at sætte værtsnavn."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
+msgid "Set static host name"
+msgstr "Sæt statisk værstnavn"
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
+msgid ""
+"Authentication is required to set the statically configured local host name, "
+"as well as the pretty host name."
+msgstr ""
+"Autentificering er nødvendig for at sætte det statisk konfigurerede lokale "
+"værtsnavn, lige så vel som det pæne værtsnavn."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
+msgid "Set machine information"
+msgstr "Sæt maskininformation."
+
+#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
+msgid "Authentication is required to set local machine information."
+msgstr "Autentificering er nødvendig for at sætte lokal maskininformation."
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:1
+msgid "Import a VM or container image"
+msgstr "Importér en VM eller container billede"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:2
+msgid "Authentication is required to import a VM or container image"
+msgstr ""
+"Autentificering er nødvendig for at importére en VM eller "
+"container billeder."
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:3
+msgid "Export a VM or container image"
+msgstr "Exportér en VM eller container billede"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:4
+msgid "Authentication is required to export a VM or container image"
+msgstr "Autentificering er nødvendig for at exportére en VM eller container billede"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:5
+msgid "Download a VM or container image"
+msgstr "Hent en VM eller container billede"
+
+#: ../src/import/org.freedesktop.import1.policy.in.h:6
+msgid "Authentication is required to download a VM or container image"
+msgstr "Autentificering er nødvendig for at hente en VM eller container billede"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
+msgid "Set system locale"
+msgstr "Sæt sprogindstillinger for systemet"
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
+msgid "Authentication is required to set the system locale."
+msgstr ""
+"Autentificering er nødvendig for at sætte sprogindstillinger "
+"for systemet."
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
+msgid "Set system keyboard settings"
+msgstr "Sæt tastaturindstillinger for systemet."
+
+#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
+msgid "Authentication is required to set the system keyboard settings."
+msgstr ""
+"Autentificering er nødvendig for at sætte tastaturindstillinger "
+"for systemet."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:1
+msgid "Allow applications to inhibit system shutdown"
+msgstr "Tillad applikationer at hæmme system nedlukning"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:2
+msgid ""
+"Authentication is required for an application to inhibit system shutdown."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan hæmme "
+"system nedlukning."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:3
+msgid "Allow applications to delay system shutdown"
+msgstr "Tillad applikationer at forsinke system nedlukning"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:4
+msgid "Authentication is required for an application to delay system shutdown."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan forsinke "
+"system nedlukning."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:5
+msgid "Allow applications to inhibit system sleep"
+msgstr "Tillad applikationer at hæmme system dvale"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:6
+msgid "Authentication is required for an application to inhibit system sleep"
+msgstr "Autentificering er nødvendig for at en applikation kan hæmme system dvale"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:7
+msgid "Allow applications to delay system sleep"
+msgstr "Tillad applikationer at forsinke system dvale"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:8
+msgid "Authentication is required for an application to delay system sleep."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan forsinke system "
+"dvale."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:9
+msgid "Allow applications to inhibit automatic system suspend"
+msgstr "Tillad applikationer at hæmme automatisk system standby"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:10
+msgid ""
+"Authentication is required for an application to inhibit automatic system "
+"suspend."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan hæmme automatisk "
+"system standby."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:11
+msgid "Allow applications to inhibit system handling of the power key"
+msgstr "Tillad applikationer at hæmme systemhåndtering af tænd/sluk-knappen"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:12
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the power key."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering "
+"af tænd/sluk-knappen."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:13
+msgid "Allow applications to inhibit system handling of the suspend key"
+msgstr "Tillad applikationer at hæmme systemhåndtering af standby-knappen"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:14
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the suspend key."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering "
+"af standby-knappen."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:15
+msgid "Allow applications to inhibit system handling of the hibernate key"
+msgstr "Tillad applikationer at hæmme systemhåndtering af dvale-knappen"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:16
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the hibernate key."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan hæmme "
+"systemhåndtering af dvale-knappen."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:17
+msgid "Allow applications to inhibit system handling of the lid switch"
+msgstr ""
+"Tillad applikationer at hæmme systemhåndtering af skærmlukning"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:18
+msgid ""
+"Authentication is required for an application to inhibit system handling of "
+"the lid switch."
+msgstr ""
+"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering "
+"af skærmlukning."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:19
+msgid "Allow non-logged-in users to run programs"
+msgstr "Tillad brugere der ikke er logget ind, at køre programmer"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:20
+msgid "Authentication is required to run programs as a non-logged-in user."
+msgstr ""
+"Autentificering er nødvendig for at brugere, som ikke er logget ind, kan "
+"køre programmer."
+
+# www.freedesktop.org/wiki/Software/systemd/multiseat/
+#: ../src/login/org.freedesktop.login1.policy.in.h:21
+msgid "Allow attaching devices to seats"
+msgstr "Tillad at montere af enheder til arbejdsstationer"
+
+# www.freedesktop.org/wiki/Software/systemd/multiseat/
+#: ../src/login/org.freedesktop.login1.policy.in.h:22
+msgid "Authentication is required for attaching a device to a seat."
+msgstr ""
+"Autentificering er nødvendig for at montere en enhed til en "
+"arbejdsstation."
+
+# www.freedesktop.org/wiki/Software/systemd/multiseat/
+#: ../src/login/org.freedesktop.login1.policy.in.h:23
+msgid "Flush device to seat attachments"
+msgstr "Nulstil enhed monteret til en arbejdsstation"
+
+# www.freedesktop.org/wiki/Software/systemd/multiseat/
+#: ../src/login/org.freedesktop.login1.policy.in.h:24
+msgid ""
+"Authentication is required for resetting how devices are attached to seats."
+msgstr ""
+"Autentificering er nødvendig for at nulstille måden enheder er monteret "
+"arbejdsstationer."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:25
+msgid "Power off the system"
+msgstr "Sluk for systemet"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:26
+msgid "Authentication is required for powering off the system."
+msgstr "Autentificering er nødvendig for at slukke systemet"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:27
+msgid "Power off the system while other users are logged in"
+msgstr "Sluk systemet mens andre brugere er logget på"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:28
+msgid ""
+"Authentication is required for powering off the system while other users are "
+"logged in."
+msgstr ""
+"Autentificering er nødvendig for at slukke systemet mens andre brugere "
+"er logget på."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:29
+msgid "Power off the system while an application asked to inhibit it"
+msgstr ""
+"Sluk for systemet mens en applikation har forespurgt at hæmme det"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:30
+msgid ""
+"Authentication is required for powering off the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Autentificering er nødvendig for at slukke systemet mens en applikation har "
+"forespurgt at hæmme det."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:31
+msgid "Reboot the system"
+msgstr "Genstart systemet"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:32
+msgid "Authentication is required for rebooting the system."
+msgstr "Autentificering er nødvendig for at genstarte systemet."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:33
+msgid "Reboot the system while other users are logged in"
+msgstr "Genstart systemet mens andre brugere er logget ind"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:34
+msgid ""
+"Authentication is required for rebooting the system while other users are "
+"logged in."
+msgstr ""
+"Autentificering er nødvendig for at genstarte systemet mens andre brugere "
+"er logget ind."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:35
+msgid "Reboot the system while an application asked to inhibit it"
+msgstr ""
+"Genstart systemet mens en applikation har forespurgt at hæmme det"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:36
+msgid ""
+"Authentication is required for rebooting the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Autentificering er nødvendig for at genstarte systemet mens en applikation "
+"har forespurgt at hæmme det."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:37
+msgid "Suspend the system"
+msgstr "Sæt systemet på standby"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:38
+msgid "Authentication is required for suspending the system."
+msgstr "Autentificering er nødvendig for at sætte systemet på standby"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:39
+msgid "Suspend the system while other users are logged in"
+msgstr "Sæt systemet på standby mens andre brugere er logget på"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:40
+msgid ""
+"Authentication is required for suspending the system while other users are "
+"logged in."
+msgstr ""
+"Autentificering er nødvendig for at sætte systemet på standby, mens andre "
+"brugere er logget på."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:41
+msgid "Suspend the system while an application asked to inhibit it"
+msgstr ""
+"Sæt systemet på standby mens en applikation har forespurgt at hæmme"
+"det"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:42
+msgid ""
+"Authentication is required for suspending the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Autentificering er nødvendig for at sætte systemet på standby, mens en "
+"applikation har forespurgt at hæmme det."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:43
+msgid "Hibernate the system"
+msgstr "Sæt systemet i dvale"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:44
+msgid "Authentication is required for hibernating the system."
+msgstr ""
+"Autentificering er nødvendig for at sætte systemet i dvale-tilstand."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:45
+msgid "Hibernate the system while other users are logged in"
+msgstr ""
+"Sæt systemet i dvale-tilstand mens andre brugere er logget på"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:46
+msgid ""
+"Authentication is required for hibernating the system while other users are "
+"logged in."
+msgstr ""
+"Autentificering er nødvendig for at sætte systemet i dvale-tilstand, mens "
+"andre brugere er logget på."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:47
+msgid "Hibernate the system while an application asked to inhibit it"
+msgstr "Sæt systemet i dvale-tilstand mens en applikation har forespurgt at "
+"hæmme det"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:48
+msgid ""
+"Authentication is required for hibernating the system while an application "
+"asked to inhibit it."
+msgstr ""
+"Autentificering er nødvendig for at sætte systemet i dvale tilstand, mens "
+"en applikation har forespurgt at hæmme det."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:49
+msgid "Manage active sessions, users and seats"
+msgstr "Håndtér aktive sessioner, brugere og arbejdsstationer"
+
+# www.freedesktop.org/wiki/Software/systemd/multiseat/
+#: ../src/login/org.freedesktop.login1.policy.in.h:50
+msgid ""
+"Authentication is required for managing active sessions, users and seats."
+msgstr ""
+"Autentificering er nødvendig for at håndtere aktive sessioner, brugere "
+"og arbejdsstationer."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:51
+msgid "Lock or unlock active sessions"
+msgstr "Lås eller oplås aktive sessioner"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:52
+msgid "Authentication is required to lock or unlock active sessions."
+msgstr ""
+"Autentificering er nødvendig for at låse eller oplåse aktive sessioner."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:53
+msgid "Allow indication to the firmware to boot to setup interface"
+msgstr "Tillad meddelelse til firmwaren om at starte op i opsætningsgrænseflade"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:54
+msgid ""
+"Authentication is required to indicate to the firmware to boot to setup "
+"interface."
+msgstr "Autentificering er nødvendig for at meddele firmwaren om at starte "
+"op i opsætningsgrænseflade."
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:55
+msgid "Set a wall message"
+msgstr "Sæt broadcast-besked"
+
+#: ../src/login/org.freedesktop.login1.policy.in.h:56
+msgid "Authentication is required to set a wall message"
+msgstr "Autentificering er nødvendig for at sætte en broadcast-besked"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
+msgid "Log into a local container"
+msgstr "Log på en lokal container"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
+msgid "Authentication is required to log into a local container."
+msgstr "Autentificering er nødvendig for at logge på en lokal container."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+msgid "Log into the local host"
+msgstr "Log på den lokale vært"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+msgid "Authentication is required to log into the local host."
+msgstr "Auitentificering er nødvendig for at logge på den lokale vært."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+msgid "Acquire a shell in a local container"
+msgstr "Anskaf en shell i en lokal container"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+msgid "Authentication is required to acquire a shell in a local container."
+msgstr ""
+"Autentificering er nødvendig for at anskaffe en shell i en lokal "
+"container."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+msgid "Acquire a shell on the local host"
+msgstr "Anskaf en shell på den lokale vært"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+msgid "Authentication is required to acquire a shell on the local host."
+msgstr ""
+"Autentificering er nødvendig for at anskaffe en shell på den lokale vært."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+msgid "Acquire a pseudo TTY in a local container"
+msgstr "Anskaf en pseudo-TTY i en lokal container"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+msgid ""
+"Authentication is required to acquire a pseudo TTY in a local container."
+msgstr ""
+"Autentificering er nødvendig for at anskaffe en pseudo-TTY i en lokal "
+"container."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+msgid "Acquire a pseudo TTY on the local host"
+msgstr "Anskaf en pseudo-TTY på den lokale vært"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+msgid "Authentication is required to acquire a pseudo TTY on the local host."
+msgstr ""
+"Autentificering er nødvendig for at anskaffe en pseudo-TTY på den "
+"lokale vært."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+msgid "Manage local virtual machines and containers"
+msgstr "Håndtér lokale virtuelle maskiner og containere"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+msgid ""
+"Authentication is required to manage local virtual machines and containers."
+msgstr ""
+"Autentificering er nødvendig for at håndtere lokale virtuelle maskiner og "
+"containere."
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
+msgid "Manage local virtual machine and container images"
+msgstr "Håndtér lokal virtuel maskine- og container billeder"
+
+#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
+msgid ""
+"Authentication is required to manage local virtual machine and container "
+"images."
+msgstr ""
+"Autentificering er nødvendig for at håndtere lokal virtuel maskine- og "
+"container billeder."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
+msgid "Set system time"
+msgstr "Sæt tiden for systemet"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
+msgid "Authentication is required to set the system time."
+msgstr "Autentificering er nødvendig for at sætte tiden for systemet."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
+msgid "Set system timezone"
+msgstr "Sæt tidszone for systemet"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
+msgid "Authentication is required to set the system timezone."
+msgstr "Autentificering er nødvendig for at sætte tidszonen for systemet."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
+msgid "Set RTC to local timezone or UTC"
+msgstr "Sæt RTC til lokal tidszone eller UTC"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
+msgid ""
+"Authentication is required to control whether the RTC stores the local or "
+"UTC time."
+msgstr ""
+"Autentificering er nødvendig for at kontrollere hvorvidt RTC'en gemmer "
+"den lokale tid eller UTC tid."
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
+msgid "Turn network time synchronization on or off"
+msgstr "Slå synkronisering af netværkstid til eller fra"
+
+#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
+msgid ""
+"Authentication is required to control whether network time synchronization "
+"shall be enabled."
+msgstr ""
+"Autentificering er nødvendig for at kontrollere hvorvidt synkronisering af "
+"netværkstid skal aktiveres"
+
+#: ../src/core/dbus-unit.c:428
+msgid "Authentication is required to start '$(unit)'."
+msgstr "Autentificering er nødvendig for at starte '$(unit)'."
+
+#: ../src/core/dbus-unit.c:429
+msgid "Authentication is required to stop '$(unit)'."
+msgstr "Autentificering er nødvendig for at stoppe '$(unit)'."
+
+#: ../src/core/dbus-unit.c:430
+msgid "Authentication is required to reload '$(unit)'."
+msgstr "Autentificering er nødvendig for at genindlæse '$(unit)'."
+
+#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432
+msgid "Authentication is required to restart '$(unit)'."
+msgstr "Autentificering at nødvendig for at genstarte '$(unit)'."
+
+#: ../src/core/dbus-unit.c:535
+msgid "Authentication is required to kill '$(unit)'."
+msgstr "Autentificering er nødvendig for at eliminere '$(unit)'."
+
+#: ../src/core/dbus-unit.c:565
+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
+msgstr ""
+"Autentificering er nødvendig for at nulstille \"fejl\" tilstanden på '$(unit)'."
+
+#: ../src/core/dbus-unit.c:597
+msgid "Authentication is required to set properties on '$(unit)'."
+msgstr ""
+"Autentificering er nødvendig for at sætte egenskaber på '$(unit)'."
+
+#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress"
+#~ msgstr ""
+#~ "Tryk Ctrl-C for at annulere alle igangværende kontrolleringer af "
+#~ "filsystemet"
+
+#~ msgid "Checking in progress on %d disk (%3.1f%% complete)"
+#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)"
+#~ msgstr[0] "Igangværende kontrollering på %d disk (%3.1f%% færdig)"
+#~ msgstr[1] "Igangværende kontrollering på %d diske (%3.1f%% færdig)"
diff --git a/shell-completion/bash/systemd-run b/shell-completion/bash/systemd-run
index be34788ab7..518812e040 100644
--- a/shell-completion/bash/systemd-run
+++ b/shell-completion/bash/systemd-run
@@ -83,7 +83,8 @@ _systemd_run() {
LimitMEMLOCK= LimitLOCKS= LimitSIGPENDING= LimitMSGQUEUE=
LimitNICE= LimitRTPRIO= LimitRTTIME= PrivateTmp= PrivateDevices=
PrivateNetwork= NoNewPrivileges= WorkingDirectory= RootDirectory=
- TTYPath='
+ TTYPath= SyslogIdentifier= SyslogLevelPrefix= SyslogLevel=
+ SyslogFacility= TimerSlackNSec='
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0
diff --git a/shell-completion/zsh/_udevadm b/shell-completion/zsh/_udevadm
index e5d252c818..bb23e64d24 100644
--- a/shell-completion/zsh/_udevadm
+++ b/shell-completion/zsh/_udevadm
@@ -89,7 +89,7 @@ _udevadm_test-builtin(){
_udevadm_mounts(){
local dev_tmp dpath_tmp mp_tmp mline
- tmp=( "${(@f)$(< /etc/mtab)}" )
+ tmp=( "${(@f)$(< /proc/self/mounts)}" )
dev_tmp=( "${(@)${(@)tmp%% *}:#none}" )
mp_tmp=( "${(@)${(@)tmp#* }%% *}" )
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c
index 2dcc9c5575..a2296f4709 100644
--- a/src/basic/calendarspec.c
+++ b/src/basic/calendarspec.c
@@ -279,6 +279,9 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) {
fputc(':', f);
format_chain(f, 2, c->second);
+ if (c->utc)
+ fputs(" UTC", f);
+
r = fflush_and_check(f);
if (r < 0) {
free(buf);
@@ -657,6 +660,10 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
if (!c)
return -ENOMEM;
+ c->utc = endswith_no_case(p, "UTC");
+ if (c->utc)
+ p = strndupa(p, strlen(p) - strlen(" UTC"));
+
if (strcaseeq(p, "minutely")) {
r = const_chain(0, &c->second);
if (r < 0)
@@ -859,13 +866,13 @@ static int find_matching_component(const CalendarComponent *c, int *val) {
return r;
}
-static bool tm_out_of_bounds(const struct tm *tm) {
+static bool tm_out_of_bounds(const struct tm *tm, bool utc) {
struct tm t;
assert(tm);
t = *tm;
- if (mktime(&t) == (time_t) -1)
+ if (mktime_or_timegm(&t, utc) == (time_t) -1)
return true;
/* Did any normalization take place? If so, it was out of bounds before */
@@ -878,7 +885,7 @@ static bool tm_out_of_bounds(const struct tm *tm) {
t.tm_sec != tm->tm_sec;
}
-static bool matches_weekday(int weekdays_bits, const struct tm *tm) {
+static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) {
struct tm t;
int k;
@@ -886,7 +893,7 @@ static bool matches_weekday(int weekdays_bits, const struct tm *tm) {
return true;
t = *tm;
- if (mktime(&t) == (time_t) -1)
+ if (mktime_or_timegm(&t, utc) == (time_t) -1)
return false;
k = t.tm_wday == 0 ? 6 : t.tm_wday - 1;
@@ -904,7 +911,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
for (;;) {
/* Normalize the current date */
- mktime(&c);
+ mktime_or_timegm(&c, spec->utc);
c.tm_isdst = -1;
c.tm_year += 1900;
@@ -916,7 +923,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
c.tm_mday = 1;
c.tm_hour = c.tm_min = c.tm_sec = 0;
}
- if (r < 0 || tm_out_of_bounds(&c))
+ if (r < 0 || tm_out_of_bounds(&c, spec->utc))
return r;
c.tm_mon += 1;
@@ -927,7 +934,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
c.tm_mday = 1;
c.tm_hour = c.tm_min = c.tm_sec = 0;
}
- if (r < 0 || tm_out_of_bounds(&c)) {
+ if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
c.tm_year ++;
c.tm_mon = 0;
c.tm_mday = 1;
@@ -938,14 +945,14 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
r = find_matching_component(spec->day, &c.tm_mday);
if (r > 0)
c.tm_hour = c.tm_min = c.tm_sec = 0;
- if (r < 0 || tm_out_of_bounds(&c)) {
+ if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
c.tm_mon ++;
c.tm_mday = 1;
c.tm_hour = c.tm_min = c.tm_sec = 0;
continue;
}
- if (!matches_weekday(spec->weekdays_bits, &c)) {
+ if (!matches_weekday(spec->weekdays_bits, &c, spec->utc)) {
c.tm_mday++;
c.tm_hour = c.tm_min = c.tm_sec = 0;
continue;
@@ -954,7 +961,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
r = find_matching_component(spec->hour, &c.tm_hour);
if (r > 0)
c.tm_min = c.tm_sec = 0;
- if (r < 0 || tm_out_of_bounds(&c)) {
+ if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
c.tm_mday ++;
c.tm_hour = c.tm_min = c.tm_sec = 0;
continue;
@@ -963,14 +970,14 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
r = find_matching_component(spec->minute, &c.tm_min);
if (r > 0)
c.tm_sec = 0;
- if (r < 0 || tm_out_of_bounds(&c)) {
+ if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
c.tm_hour ++;
c.tm_min = c.tm_sec = 0;
continue;
}
r = find_matching_component(spec->second, &c.tm_sec);
- if (r < 0 || tm_out_of_bounds(&c)) {
+ if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
c.tm_min ++;
c.tm_sec = 0;
continue;
@@ -991,13 +998,13 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next)
assert(next);
t = (time_t) (usec / USEC_PER_SEC) + 1;
- assert_se(localtime_r(&t, &tm));
+ assert_se(localtime_or_gmtime_r(&t, &tm, spec->utc));
r = find_next(spec, &tm);
if (r < 0)
return r;
- t = mktime(&tm);
+ t = mktime_or_timegm(&tm, spec->utc);
if (t == (time_t) -1)
return -EINVAL;
diff --git a/src/basic/calendarspec.h b/src/basic/calendarspec.h
index 7baf318249..56dc02f391 100644
--- a/src/basic/calendarspec.h
+++ b/src/basic/calendarspec.h
@@ -36,6 +36,7 @@ typedef struct CalendarComponent {
typedef struct CalendarSpec {
int weekdays_bits;
+ bool utc;
CalendarComponent *year;
CalendarComponent *month;
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 59e835a466..5fb9951a84 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -126,6 +126,10 @@
#define SOL_NETLINK 270
#endif
+#ifndef NETLINK_LIST_MEMBERSHIPS
+#define NETLINK_LIST_MEMBERSHIPS 9
+#endif
+
#if !HAVE_DECL_PIVOT_ROOT
static inline int pivot_root(const char *new_root, const char *put_old) {
return syscall(SYS_pivot_root, new_root, put_old);
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index 531931f6e1..d4e0914b27 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -19,7 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <time.h>
#include <string.h>
#include <sys/timex.h>
#include <sys/timerfd.h>
@@ -205,11 +204,8 @@ static char *format_timestamp_internal(char *buf, size_t l, usec_t t, bool utc)
return NULL;
sec = (time_t) (t / USEC_PER_SEC);
+ localtime_or_gmtime_r(&sec, &tm, utc);
- if (utc)
- gmtime_r(&sec, &tm);
- else
- localtime_r(&sec, &tm);
if (strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", &tm) <= 0)
return NULL;
@@ -235,10 +231,7 @@ static char *format_timestamp_internal_us(char *buf, size_t l, usec_t t, bool ut
return NULL;
sec = (time_t) (t / USEC_PER_SEC);
- if (utc)
- gmtime_r(&sec, &tm);
- else
- localtime_r(&sec, &tm);
+ localtime_or_gmtime_r(&sec, &tm, utc);
if (strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm) <= 0)
return NULL;
@@ -484,9 +477,10 @@ int parse_timestamp(const char *t, usec_t *usec) {
};
const char *k;
+ bool utc;
struct tm tm, copy;
time_t x;
- usec_t plus = 0, minus = 0, ret;
+ usec_t x_usec, plus = 0, minus = 0, ret;
int r, weekday = -1;
unsigned i;
@@ -511,28 +505,15 @@ int parse_timestamp(const char *t, usec_t *usec) {
assert(t);
assert(usec);
- x = time(NULL);
- assert_se(localtime_r(&x, &tm));
- tm.tm_isdst = -1;
-
- if (streq(t, "now"))
- goto finish;
-
- else if (streq(t, "today")) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
+ if (t[0] == '@')
+ return parse_sec(t + 1, usec);
- } else if (streq(t, "yesterday")) {
- tm.tm_mday --;
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
+ ret = now(CLOCK_REALTIME);
- } else if (streq(t, "tomorrow")) {
- tm.tm_mday ++;
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
+ if (streq(t, "now"))
goto finish;
- } else if (t[0] == '+') {
+ else if (t[0] == '+') {
r = parse_sec(t+1, &plus);
if (r < 0)
return r;
@@ -546,35 +527,51 @@ int parse_timestamp(const char *t, usec_t *usec) {
goto finish;
- } else if (t[0] == '@')
- return parse_sec(t + 1, usec);
-
- else if (endswith(t, " ago")) {
- _cleanup_free_ char *z;
-
- z = strndup(t, strlen(t) - 4);
- if (!z)
- return -ENOMEM;
+ } else if (endswith(t, " ago")) {
+ t = strndupa(t, strlen(t) - strlen(" ago"));
- r = parse_sec(z, &minus);
+ r = parse_sec(t, &minus);
if (r < 0)
return r;
goto finish;
- } else if (endswith(t, " left")) {
- _cleanup_free_ char *z;
- z = strndup(t, strlen(t) - 4);
- if (!z)
- return -ENOMEM;
+ } else if (endswith(t, " left")) {
+ t = strndupa(t, strlen(t) - strlen(" left"));
- r = parse_sec(z, &plus);
+ r = parse_sec(t, &plus);
if (r < 0)
return r;
goto finish;
}
+ utc = endswith_no_case(t, " UTC");
+ if (utc)
+ t = strndupa(t, strlen(t) - strlen(" UTC"));
+
+ x = ret / USEC_PER_SEC;
+ x_usec = 0;
+
+ assert_se(localtime_or_gmtime_r(&x, &tm, utc));
+ tm.tm_isdst = -1;
+
+ if (streq(t, "today")) {
+ tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
+ goto from_tm;
+
+ } else if (streq(t, "yesterday")) {
+ tm.tm_mday --;
+ tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
+ goto from_tm;
+
+ } else if (streq(t, "tomorrow")) {
+ tm.tm_mday ++;
+ tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
+ goto from_tm;
+ }
+
+
for (i = 0; i < ELEMENTSOF(day_nr); i++) {
size_t skip;
@@ -592,66 +589,106 @@ int parse_timestamp(const char *t, usec_t *usec) {
copy = tm;
k = strptime(t, "%y-%m-%d %H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
+ if (k) {
+ if (*k == '.')
+ goto parse_usec;
+ else if (*k == 0)
+ goto from_tm;
+ }
tm = copy;
k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
+ if (k) {
+ if (*k == '.')
+ goto parse_usec;
+ else if (*k == 0)
+ goto from_tm;
+ }
tm = copy;
k = strptime(t, "%y-%m-%d %H:%M", &tm);
if (k && *k == 0) {
tm.tm_sec = 0;
- goto finish;
+ goto from_tm;
}
tm = copy;
k = strptime(t, "%Y-%m-%d %H:%M", &tm);
if (k && *k == 0) {
tm.tm_sec = 0;
- goto finish;
+ goto from_tm;
}
tm = copy;
k = strptime(t, "%y-%m-%d", &tm);
if (k && *k == 0) {
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
+ goto from_tm;
}
tm = copy;
k = strptime(t, "%Y-%m-%d", &tm);
if (k && *k == 0) {
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
+ goto from_tm;
}
tm = copy;
k = strptime(t, "%H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
+ if (k) {
+ if (*k == '.')
+ goto parse_usec;
+ else if (*k == 0)
+ goto from_tm;
+ }
tm = copy;
k = strptime(t, "%H:%M", &tm);
if (k && *k == 0) {
tm.tm_sec = 0;
- goto finish;
+ goto from_tm;
}
return -EINVAL;
-finish:
- x = mktime(&tm);
+parse_usec:
+ {
+ char *end;
+ unsigned long long val;
+ size_t l;
+
+ k++;
+ if (*k < '0' || *k > '9')
+ return -EINVAL;
+
+ /* base 10 instead of base 0, .09 is not base 8 */
+ errno = 0;
+ val = strtoull(k, &end, 10);
+ if (*end || errno)
+ return -EINVAL;
+
+ l = end-k;
+
+ /* val has l digits, make them 6 */
+ for (; l < 6; l++)
+ val *= 10;
+ for (; l > 6; l--)
+ val /= 10;
+
+ x_usec = val;
+ }
+
+from_tm:
+ x = mktime_or_timegm(&tm, utc);
if (x == (time_t) -1)
return -EINVAL;
if (weekday >= 0 && tm.tm_wday != weekday)
return -EINVAL;
- ret = (usec_t) x * USEC_PER_SEC;
+ ret = (usec_t) x * USEC_PER_SEC + x_usec;
+finish:
ret += plus;
if (ret > minus)
ret -= minus;
@@ -1072,3 +1109,11 @@ int get_timezone(char **tz) {
*tz = z;
return 0;
}
+
+time_t mktime_or_timegm(struct tm *tm, bool utc) {
+ return utc ? timegm(tm) : mktime(tm);
+}
+
+struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc) {
+ return utc ? gmtime_r(t, tm) : localtime_r(t, tm);
+}
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
index 1af01541fc..417376ea96 100644
--- a/src/basic/time-util.h
+++ b/src/basic/time-util.h
@@ -21,8 +21,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <inttypes.h>
+#include <stdio.h>
+#include <time.h>
typedef uint64_t usec_t;
typedef uint64_t nsec_t;
@@ -117,3 +118,6 @@ clockid_t clock_boottime_or_monotonic(void);
"xstrftime: " #buf "[] must be big enough")
int get_timezone(char **timezone);
+
+time_t mktime_or_timegm(struct tm *tm, bool utc);
+struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc);
diff --git a/src/basic/util.c b/src/basic/util.c
index ca5e4befa0..8b896a2df3 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -3699,6 +3699,10 @@ static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
+bool log_facility_unshifted_is_valid(int facility) {
+ return facility >= 0 && facility <= LOG_FAC(~0);
+}
+
static const char *const log_level_table[] = {
[LOG_EMERG] = "emerg",
[LOG_ALERT] = "alert",
@@ -3712,6 +3716,10 @@ static const char *const log_level_table[] = {
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
+bool log_level_is_valid(int level) {
+ return level >= 0 && level <= LOG_DEBUG;
+}
+
static const char* const sched_policy_table[] = {
[SCHED_OTHER] = "other",
[SCHED_BATCH] = "batch",
diff --git a/src/basic/util.h b/src/basic/util.h
index 79c7ad1b39..2544ad0830 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -456,9 +456,11 @@ int sigchld_code_from_string(const char *s) _pure_;
int log_facility_unshifted_to_string_alloc(int i, char **s);
int log_facility_unshifted_from_string(const char *s);
+bool log_facility_unshifted_is_valid(int faciliy);
int log_level_to_string_alloc(int i, char **s);
int log_level_from_string(const char *s);
+bool log_level_is_valid(int level);
int sched_policy_to_string_alloc(int i, char **s);
int sched_policy_from_string(const char *s);
diff --git a/src/core/busname.c b/src/core/busname.c
index 38becfc119..b85fce5f8d 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -585,6 +585,12 @@ static void busname_enter_running(BusName *n) {
}
if (!pending) {
+ if (!UNIT_ISSET(n->service)) {
+ log_unit_error(UNIT(n), "Service to activate vanished, refusing activation.");
+ r = -ENOENT;
+ goto fail;
+ }
+
r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
if (r < 0)
goto fail;
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index adf613d328..436229330e 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -83,45 +83,6 @@ static int property_get_environment_files(
return sd_bus_message_close_container(reply);
}
-static int property_get_rlimit(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- struct rlimit *rl;
- uint64_t u;
- rlim_t x;
-
- assert(bus);
- assert(reply);
- assert(userdata);
-
- rl = *(struct rlimit**) userdata;
- if (rl)
- x = rl->rlim_max;
- else {
- struct rlimit buf = {};
- int z;
-
- z = rlimit_from_string(property);
- assert(z >= 0);
-
- getrlimit(z, &buf);
- x = buf.rlim_max;
- }
-
- /* rlim_t might have different sizes, let's map
- * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
- * all archs */
- u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
-
- return sd_bus_message_append(reply, "t", u);
-}
-
static int property_get_oom_score_adjust(
sd_bus *bus,
const char *path,
@@ -622,27 +583,63 @@ static int property_get_working_directory(
return sd_bus_message_append(reply, "s", wd);
}
+static int property_get_syslog_level(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ ExecContext *c = userdata;
+
+ assert(bus);
+ assert(reply);
+ assert(c);
+
+ return sd_bus_message_append(reply, "i", LOG_PRI(c->syslog_priority));
+}
+
+static int property_get_syslog_facility(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ ExecContext *c = userdata;
+
+ assert(bus);
+ assert(reply);
+ assert(c);
+
+ return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority));
+}
+
const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -664,6 +661,8 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -856,7 +855,64 @@ int bus_exec_context_set_transient_property(
}
return 1;
+ } else if (streq(name, "SyslogIdentifier")) {
+ const char *id;
+
+ r = sd_bus_message_read(message, "s", &id);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+
+ if (isempty(id)) {
+ c->syslog_identifier = mfree(c->syslog_identifier);
+ } else {
+ char *t;
+
+ t = strdup(id);
+ if (!t)
+ return -ENOMEM;
+
+ free(c->syslog_identifier);
+ c->syslog_identifier = t;
+ }
+
+ unit_write_drop_in_private_format(u, mode, name, "SyslogIdentifier=%s\n", id);
+ }
+
+ return 1;
+ } else if (streq(name, "SyslogLevel")) {
+ int level;
+
+ r = sd_bus_message_read(message, "i", &level);
+ if (r < 0)
+ return r;
+
+ if (!log_level_is_valid(level))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
+
+ if (mode != UNIT_CHECK) {
+ c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
+ unit_write_drop_in_private_format(u, mode, name, "SyslogLevel=%i\n", level);
+ }
+
+ return 1;
+ } else if (streq(name, "SyslogFacility")) {
+ int facility;
+ r = sd_bus_message_read(message, "i", &facility);
+ if (r < 0)
+ return r;
+
+ if (!log_facility_unshifted_is_valid(facility))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
+
+ if (mode != UNIT_CHECK) {
+ c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
+ unit_write_drop_in_private_format(u, mode, name, "SyslogFacility=%i\n", facility);
+ }
+
+ return 1;
} else if (streq(name, "Nice")) {
int n;
@@ -998,7 +1054,7 @@ int bus_exec_context_set_transient_property(
} else if (STR_IN_SET(name,
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
"PrivateTmp", "PrivateDevices", "PrivateNetwork",
- "NoNewPrivileges")) {
+ "NoNewPrivileges", "SyslogLevelPrefix")) {
int b;
r = sd_bus_message_read(message, "b", &b);
@@ -1020,6 +1076,8 @@ int bus_exec_context_set_transient_property(
c->private_network = b;
else if (streq(name, "NoNewPrivileges"))
c->no_new_privileges = b;
+ else if (streq(name, "SyslogLevelPrefix"))
+ c->syslog_level_prefix = b;
unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, yes_no(b));
}
@@ -1113,6 +1171,21 @@ int bus_exec_context_set_transient_property(
return 1;
+ } else if (streq(name, "TimerSlackNSec")) {
+
+ nsec_t n;
+
+ r = sd_bus_message_read(message, "t", &n);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ c->timer_slack_nsec = n;
+ unit_write_drop_in_private_format(u, mode, name, "TimerSlackNSec=" NSEC_FMT "\n", n);
+ }
+
+ return 1;
+
} else if (rlimit_from_string(name) >= 0) {
uint64_t rl;
rlim_t x;
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 9e21b0787d..00bb391106 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -20,6 +20,7 @@
***/
#include <errno.h>
+#include <sys/prctl.h>
#include <unistd.h>
#include "log.h"
@@ -122,8 +123,7 @@ static int property_get_tainted(
void *userdata,
sd_bus_error *error) {
- char buf[sizeof("split-usr:mtab-not-symlink:cgroups-missing:local-hwclock:")] = "", *e = buf;
- _cleanup_free_ char *p = NULL;
+ char buf[sizeof("split-usr:cgroups-missing:local-hwclock:")] = "", *e = buf;
Manager *m = userdata;
assert(bus);
@@ -133,9 +133,6 @@ static int property_get_tainted(
if (m->taint_usr)
e = stpcpy(e, "split-usr:");
- if (readlink_malloc("/etc/mtab", &p) < 0)
- e = stpcpy(e, "mtab-not-symlink:");
-
if (access("/proc/cgroups", F_OK) < 0)
e = stpcpy(e, "cgroups-missing:");
@@ -350,6 +347,21 @@ static int property_set_runtime_watchdog(
return watchdog_set_timeout(t);
}
+static int property_get_timer_slack_nsec(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ assert(bus);
+ assert(reply);
+
+ return sd_bus_message_append(reply, "t", (uint64_t) prctl(PR_GET_TIMERSLACK));
+}
+
static int method_get_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *path = NULL;
Manager *m = userdata;
@@ -1981,6 +1993,23 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("DefaultBlockIOAccounting", "b", bus_property_get_bool, offsetof(Manager, default_blockio_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultMemoryAccounting", "b", bus_property_get_bool, offsetof(Manager, default_memory_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultTasksAccounting", "b", bus_property_get_bool, offsetof(Manager, default_tasks_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitCPU", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitFSIZE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitDATA", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitSTACK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitCORE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitRSS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitNOFILE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitAS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitNPROC", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitLOCKS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitNICE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitRTPRIO", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultLimitRTTIME", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
diff --git a/src/core/execute.c b/src/core/execute.c
index d6217840c0..51efb7c215 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -2314,7 +2314,7 @@ static void strv_fprintf(FILE *f, char **l) {
}
void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
- char **e;
+ char **e, **d;
unsigned i;
assert(c);
@@ -2350,6 +2350,11 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
STRV_FOREACH(e, c->environment_files)
fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
+ fprintf(f, "%sRuntimeDirectoryMode: %04o\n", prefix, c->runtime_directory_mode);
+
+ STRV_FOREACH(d, c->runtime_directory)
+ fprintf(f, "%sRuntimeDirectory: %s\n", prefix, *d);
+
if (c->nice_set)
fprintf(f,
"%sNice: %i\n",
diff --git a/src/core/manager.c b/src/core/manager.c
index 526d4d1cef..b2d56e88a7 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -3013,30 +3013,6 @@ void manager_status_printf(Manager *m, StatusType type, const char *status, cons
va_end(ap);
}
-int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found) {
- _cleanup_free_ char *p = NULL;
- Unit *found;
- int r;
-
- assert(m);
- assert(path);
- assert(suffix);
- assert(_found);
-
- r = unit_name_from_path(path, suffix, &p);
- if (r < 0)
- return r;
-
- found = manager_get_unit(m, p);
- if (!found) {
- *_found = NULL;
- return 0;
- }
-
- *_found = found;
- return 1;
-}
-
Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
char p[strlen(path)+1];
diff --git a/src/core/manager.h b/src/core/manager.h
index fad10aaacf..38d2770e97 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -322,8 +322,6 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds);
Job *manager_get_job(Manager *m, uint32_t id);
Unit *manager_get_unit(Manager *m, const char *name);
-int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found);
-
int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
diff --git a/src/core/scope.c b/src/core/scope.c
index 7325e3601b..ea7d846578 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -534,6 +534,9 @@ static int scope_enumerate(Manager *m) {
u->transient = true;
u->default_dependencies = false;
u->no_gc = true;
+ u->ignore_on_isolate = true;
+ u->refuse_manual_start = true;
+ u->refuse_manual_stop = true;
SCOPE(u)->deserialized_state = SCOPE_RUNNING;
SCOPE(u)->kill_context.kill_signal = SIGRTMIN+14;
diff --git a/src/core/slice.c b/src/core/slice.c
index 063024134a..1542e83eb6 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -274,6 +274,9 @@ static int slice_enumerate(Manager *m) {
u->default_dependencies = false;
u->no_gc = true;
+ u->ignore_on_isolate = true;
+ u->refuse_manual_start = true;
+ u->refuse_manual_stop = true;
SLICE(u)->deserialized_state = SLICE_ACTIVE;
if (!u->description)
diff --git a/src/core/unit.c b/src/core/unit.c
index 423caa9562..39cd89f1e3 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1147,13 +1147,23 @@ static int unit_add_mount_dependencies(Unit *u) {
char prefix[strlen(*i) + 1];
PATH_FOREACH_PREFIX_MORE(prefix, *i) {
+ _cleanup_free_ char *p = NULL;
Unit *m;
- r = manager_get_unit_by_path(u->manager, prefix, ".mount", &m);
+ r = unit_name_from_path(prefix, ".mount", &p);
if (r < 0)
return r;
- if (r == 0)
+
+ m = manager_get_unit(u->manager, p);
+ if (!m) {
+ /* Make sure to load the mount unit if
+ * it exists. If so the dependencies
+ * on this unit will be added later
+ * during the loading of the mount
+ * unit. */
+ (void) manager_load_unit_prepare(u->manager, p, NULL, NULL, &m);
continue;
+ }
if (m == u)
continue;
diff --git a/src/journal/compress.c b/src/journal/compress.c
index c66043e503..8c92e26edd 100644
--- a/src/journal/compress.c
+++ b/src/journal/compress.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sys/mman.h>
#ifdef HAVE_XZ
# include <lzma.h>
@@ -29,6 +30,7 @@
#ifdef HAVE_LZ4
# include <lz4.h>
+# include <lz4frame.h>
#endif
#include "compress.h"
@@ -37,6 +39,11 @@
#include "sparse-endian.h"
#include "journal-def.h"
+#ifdef HAVE_LZ4
+DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_compressionContext_t, LZ4F_freeCompressionContext);
+DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_decompressionContext_t, LZ4F_freeDecompressionContext);
+#endif
+
#define ALIGN_8(l) ALIGN_TO(l, sizeof(size_t))
static const char* const object_compressed_table[_OBJECT_COMPRESSED_MAX] = {
@@ -416,81 +423,96 @@ int compress_stream_xz(int fdf, int fdt, uint64_t max_bytes) {
#endif
}
-#define LZ4_BUFSIZE (512*1024)
+#define LZ4_BUFSIZE (512*1024u)
int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
#ifdef HAVE_LZ4
+ LZ4F_errorCode_t c;
+ _cleanup_(LZ4F_freeCompressionContextp) LZ4F_compressionContext_t ctx = NULL;
+ _cleanup_free_ char *buf = NULL;
+ char *src = NULL;
+ size_t size, n, total_in = 0, total_out = 0, offset = 0, frame_size;
+ struct stat st;
+ int r;
+ static const LZ4F_compressOptions_t options = {
+ .stableSrc = 1,
+ };
+ static const LZ4F_preferences_t preferences = {
+ .frameInfo.blockSizeID = 5,
+ };
- _cleanup_free_ char *buf1 = NULL, *buf2 = NULL, *out = NULL;
- char *buf;
- LZ4_stream_t lz4_data = {};
- le32_t header;
- size_t total_in = 0, total_out = sizeof(header);
- ssize_t n;
+ c = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
+ if (LZ4F_isError(c))
+ return -ENOMEM;
- assert(fdf >= 0);
- assert(fdt >= 0);
+ if (fstat(fdf, &st) < 0)
+ return log_debug_errno(errno, "fstat() failed: %m");
- buf1 = malloc(LZ4_BUFSIZE);
- buf2 = malloc(LZ4_BUFSIZE);
- out = malloc(LZ4_COMPRESSBOUND(LZ4_BUFSIZE));
- if (!buf1 || !buf2 || !out)
- return log_oom();
+ frame_size = LZ4F_compressBound(LZ4_BUFSIZE, &preferences);
+ size = frame_size + 64*1024; /* add some space for header and trailer */
+ buf = malloc(size);
+ if (!buf)
+ return -ENOMEM;
- buf = buf1;
- for (;;) {
- size_t m;
- int r;
+ n = offset = LZ4F_compressBegin(ctx, buf, size, &preferences);
+ if (LZ4F_isError(n))
+ return -EINVAL;
- m = LZ4_BUFSIZE;
- if (max_bytes != (uint64_t) -1 && (uint64_t) m > (max_bytes - total_in))
- m = (size_t) (max_bytes - total_in);
+ src = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fdf, 0);
+ if (src == MAP_FAILED)
+ return -errno;
- n = read(fdf, buf, m);
- if (n < 0)
- return -errno;
- if (n == 0)
- break;
+ log_debug("Buffer size is %zu bytes, header size %zu bytes.", size, n);
- total_in += n;
+ while (total_in < (size_t) st.st_size) {
+ ssize_t k;
- r = LZ4_compress_continue(&lz4_data, buf, out, n);
- if (r == 0) {
- log_error("LZ4 compression failed.");
- return -EBADMSG;
+ k = MIN(LZ4_BUFSIZE, st.st_size - total_in);
+ n = LZ4F_compressUpdate(ctx, buf + offset, size - offset,
+ src + total_in, k, &options);
+ if (LZ4F_isError(n)) {
+ r = -ENOTRECOVERABLE;
+ goto cleanup;
}
- header = htole32(r);
- errno = 0;
+ total_in += k;
+ offset += n;
+ total_out += n;
- n = write(fdt, &header, sizeof(header));
- if (n < 0)
- return -errno;
- if (n != sizeof(header))
- return errno ? -errno : -EIO;
-
- n = loop_write(fdt, out, r, false);
- if (n < 0)
- return n;
+ if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes) {
+ log_debug("Compressed stream longer than %zd bytes", max_bytes);
+ return -EFBIG;
+ }
- total_out += sizeof(header) + r;
+ if (size - offset < frame_size + 4) {
+ k = loop_write(fdt, buf, offset, false);
+ if (k < 0) {
+ r = k;
+ goto cleanup;
+ }
+ offset = 0;
+ }
+ }
- buf = buf == buf1 ? buf2 : buf1;
+ n = LZ4F_compressEnd(ctx, buf + offset, size - offset, &options);
+ if (LZ4F_isError(n)) {
+ r = -ENOTRECOVERABLE;
+ goto cleanup;
}
- header = htole32(0);
- n = write(fdt, &header, sizeof(header));
- if (n < 0)
- return -errno;
- if (n != sizeof(header))
- return errno ? -errno : -EIO;
+ offset += n;
+ total_out += n;
+ r = loop_write(fdt, buf, offset, false);
+ if (r < 0)
+ goto cleanup;
log_debug("LZ4 compression finished (%zu -> %zu bytes, %.1f%%)",
total_in, total_out,
(double) total_out / total_in * 100);
-
- return 0;
+ cleanup:
+ munmap(src, st.st_size);
+ return r;
#else
return -EPROTONOSUPPORT;
#endif
@@ -510,7 +532,7 @@ int decompress_stream_xz(int fdf, int fdt, uint64_t max_bytes) {
ret = lzma_stream_decoder(&s, UINT64_MAX, 0);
if (ret != LZMA_OK) {
- log_error("Failed to initialize XZ decoder: code %u", ret);
+ log_debug("Failed to initialize XZ decoder: code %u", ret);
return -ENOMEM;
}
@@ -536,7 +558,7 @@ int decompress_stream_xz(int fdf, int fdt, uint64_t max_bytes) {
ret = lzma_code(&s, action);
if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
- log_error("Decompression failed: code %u", ret);
+ log_debug("Decompression failed: code %u", ret);
return -EBADMSG;
}
@@ -566,14 +588,14 @@ int decompress_stream_xz(int fdf, int fdt, uint64_t max_bytes) {
}
}
#else
- log_error("Cannot decompress file. Compiled without XZ support.");
+ log_debug("Cannot decompress file. Compiled without XZ support.");
return -EPROTONOSUPPORT;
#endif
}
-int decompress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
-
#ifdef HAVE_LZ4
+static int decompress_stream_lz4_v1(int fdf, int fdt, uint64_t max_bytes) {
+
_cleanup_free_ char *buf = NULL, *out = NULL;
size_t buf_size = 0;
LZ4_streamDecode_t lz4_data = {};
@@ -585,7 +607,7 @@ int decompress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
out = malloc(4*LZ4_BUFSIZE);
if (!out)
- return log_oom();
+ return -ENOMEM;
for (;;) {
ssize_t m;
@@ -606,22 +628,24 @@ int decompress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
* not accept buffers compressed by newer binaries then.
*/
if (m > LZ4_COMPRESSBOUND(LZ4_BUFSIZE * 4)) {
- log_error("Compressed stream block too big: %zd bytes", m);
- return -EBADMSG;
+ log_debug("Compressed stream block too big: %zd bytes", m);
+ return -ENOBUFS;
}
total_in += sizeof(header) + m;
if (!GREEDY_REALLOC(buf, buf_size, m))
- return log_oom();
+ return -ENOMEM;
r = loop_read_exact(fdf, buf, m, false);
if (r < 0)
return r;
r = LZ4_decompress_safe_continue(&lz4_data, buf, out, m, 4*LZ4_BUFSIZE);
- if (r <= 0)
- log_error("LZ4 decompression failed.");
+ if (r <= 0) {
+ log_debug("LZ4 decompression failed (legacy format).");
+ return -EBADMSG;
+ }
total_out += r;
@@ -635,13 +659,80 @@ int decompress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
return r;
}
- log_debug("LZ4 decompression finished (%zu -> %zu bytes, %.1f%%)",
+ log_debug("LZ4 decompression finished (legacy format, %zu -> %zu bytes, %.1f%%)",
total_in, total_out,
(double) total_out / total_in * 100);
return 0;
+}
+
+static int decompress_stream_lz4_v2(int in, int out, uint64_t max_bytes) {
+ size_t c;
+ _cleanup_(LZ4F_freeDecompressionContextp) LZ4F_decompressionContext_t ctx = NULL;
+ _cleanup_free_ char *buf = NULL;
+ char *src;
+ struct stat st;
+ int r = 0;
+ size_t total_in = 0, total_out = 0;
+
+ c = LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION);
+ if (LZ4F_isError(c))
+ return -ENOMEM;
+
+ if (fstat(in, &st) < 0)
+ return log_debug_errno(errno, "fstat() failed: %m");
+
+ buf = malloc(LZ4_BUFSIZE);
+ if (!buf)
+ return -ENOMEM;
+
+ src = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, in, 0);
+ if (src == MAP_FAILED)
+ return -errno;
+
+ while (total_in < (size_t) st.st_size) {
+ size_t produced = LZ4_BUFSIZE;
+ size_t used = st.st_size - total_in;
+
+ c = LZ4F_decompress(ctx, buf, &produced, src + total_in, &used, NULL);
+ if (LZ4F_isError(c)) {
+ r = -EBADMSG;
+ goto cleanup;
+ }
+
+ total_in += used;
+ total_out += produced;
+
+ if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes) {
+ log_debug("Decompressed stream longer than %zd bytes", max_bytes);
+ r = -EFBIG;
+ goto cleanup;
+ }
+
+ r = loop_write(out, buf, produced, false);
+ if (r < 0)
+ goto cleanup;
+ }
+
+ log_debug("LZ4 decompression finished (%zu -> %zu bytes, %.1f%%)",
+ total_in, total_out,
+ (double) total_out / total_in * 100);
+ cleanup:
+ munmap(src, st.st_size);
+ return r;
+}
+#endif
+
+int decompress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
+#ifdef HAVE_LZ4
+ int r;
+
+ r = decompress_stream_lz4_v2(fdf, fdt, max_bytes);
+ if (r == -EBADMSG)
+ r = decompress_stream_lz4_v1(fdf, fdt, max_bytes);
+ return r;
#else
- log_error("Cannot decompress file. Compiled without LZ4 support.");
+ log_debug("Cannot decompress file. Compiled without LZ4 support.");
return -EPROTONOSUPPORT;
#endif
}
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index d9851db36c..5dafb0bcab 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -194,8 +194,8 @@ static void help(void) {
" --system Show the system journal\n"
" --user Show the user journal for the current user\n"
" -M --machine=CONTAINER Operate on local container\n"
- " --since=DATE Show entries not older than the specified date\n"
- " --until=DATE Show entries not newer than the specified date\n"
+ " -S --since=DATE Show entries not older than the specified date\n"
+ " -U --until=DATE Show entries not newer than the specified date\n"
" -c --cursor=CURSOR Show entries starting at the specified cursor\n"
" --after-cursor=CURSOR Show entries after the specified cursor\n"
" --show-cursor Print the cursor after all the entries\n"
@@ -270,8 +270,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_VERIFY,
ARG_VERIFY_KEY,
ARG_DISK_USAGE,
- ARG_SINCE,
- ARG_UNTIL,
ARG_AFTER_CURSOR,
ARG_SHOW_CURSOR,
ARG_USER_UNIT,
@@ -323,8 +321,8 @@ static int parse_argv(int argc, char *argv[]) {
{ "cursor", required_argument, NULL, 'c' },
{ "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR },
{ "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR },
- { "since", required_argument, NULL, ARG_SINCE },
- { "until", required_argument, NULL, ARG_UNTIL },
+ { "since", required_argument, NULL, 'S' },
+ { "until", required_argument, NULL, 'U' },
{ "unit", required_argument, NULL, 'u' },
{ "user-unit", required_argument, NULL, ARG_USER_UNIT },
{ "field", required_argument, NULL, 'F' },
@@ -348,7 +346,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:t:u:F:xrM:", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:S:U:t:u:F:xrM:", options, NULL)) >= 0)
switch (c) {
@@ -646,7 +644,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
- case ARG_SINCE:
+ case 'S':
r = parse_timestamp(optarg, &arg_since);
if (r < 0) {
log_error("Failed to parse timestamp: %s", optarg);
@@ -655,7 +653,7 @@ static int parse_argv(int argc, char *argv[]) {
arg_since_set = true;
break;
- case ARG_UNTIL:
+ case 'U':
r = parse_timestamp(optarg, &arg_until);
if (r < 0) {
log_error("Failed to parse timestamp: %s", optarg);
@@ -748,7 +746,7 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
- if (arg_action != ACTION_SHOW && optind < argc) {
+ if (!IN_SET(arg_action, ACTION_SHOW, ACTION_DUMP_CATALOG, ACTION_LIST_CATALOG) && optind < argc) {
log_error("Extraneous arguments starting with '%s'", argv[optind]);
return -EINVAL;
}
@@ -1879,6 +1877,7 @@ int main(int argc, char *argv[]) {
} else {
bool oneline = arg_action == ACTION_LIST_CATALOG;
+ pager_open_if_enabled();
if (optind < argc)
r = catalog_list_items(stdout, database,
oneline, argv + optind);
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index fb172b7f5d..2d2a215f5d 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -1446,6 +1446,7 @@ static int server_open_hostname(Server *s) {
int server_init(Server *s) {
_cleanup_fdset_free_ FDSet *fds = NULL;
int n, r, fd;
+ bool no_sockets;
assert(s);
@@ -1555,30 +1556,44 @@ int server_init(Server *s) {
}
}
- r = server_open_stdout_socket(s, fds);
- if (r < 0)
- return r;
+ /* Try to restore streams, but don't bother if this fails */
+ (void) server_restore_streams(s, fds);
if (fdset_size(fds) > 0) {
log_warning("%u unknown file descriptors passed, closing.", fdset_size(fds));
fds = fdset_free(fds);
}
+ no_sockets = s->native_fd < 0 && s->stdout_fd < 0 && s->syslog_fd < 0 && s->audit_fd < 0;
+
+ /* always open stdout, syslog, native, and kmsg sockets */
+
+ /* systemd-journald.socket: /run/systemd/journal/stdout */
+ r = server_open_stdout_socket(s);
+ if (r < 0)
+ return r;
+
+ /* systemd-journald-dev-log.socket: /run/systemd/journal/dev-log */
r = server_open_syslog_socket(s);
if (r < 0)
return r;
+ /* systemd-journald.socket: /run/systemd/journal/socket */
r = server_open_native_socket(s);
if (r < 0)
return r;
+ /* /dev/ksmg */
r = server_open_dev_kmsg(s);
if (r < 0)
return r;
- r = server_open_audit(s);
- if (r < 0)
- return r;
+ /* Unless we got *some* sockets and not audit, open audit socket */
+ if (s->audit_fd >= 0 || no_sockets) {
+ r = server_open_audit(s);
+ if (r < 0)
+ return r;
+ }
r = server_open_kernel_seqnum(s);
if (r < 0)
diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
index 69e2d41863..cbdaa3b888 100644
--- a/src/journal/journald-stream.c
+++ b/src/journal/journald-stream.c
@@ -627,7 +627,7 @@ static int stdout_stream_restore(Server *s, const char *fname, int fd) {
return 0;
}
-static int server_restore_streams(Server *s, FDSet *fds) {
+int server_restore_streams(Server *s, FDSet *fds) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
int r;
@@ -681,7 +681,7 @@ fail:
return log_error_errno(errno, "Failed to read streams directory: %m");
}
-int server_open_stdout_socket(Server *s, FDSet *fds) {
+int server_open_stdout_socket(Server *s) {
int r;
assert(s);
@@ -717,8 +717,5 @@ int server_open_stdout_socket(Server *s, FDSet *fds) {
if (r < 0)
return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m");
- /* Try to restore streams, but don't bother if this fails */
- (void) server_restore_streams(s, fds);
-
return 0;
}
diff --git a/src/journal/journald-stream.h b/src/journal/journald-stream.h
index 94bf955d78..257dce45df 100644
--- a/src/journal/journald-stream.h
+++ b/src/journal/journald-stream.h
@@ -24,6 +24,6 @@
#include "fdset.h"
#include "journald-server.h"
-int server_open_stdout_socket(Server *s, FDSet *fds);
-
+int server_open_stdout_socket(Server *s);
+int server_restore_streams(Server *s, FDSet *fds);
void stdout_stream_free(StdoutStream *s);
diff --git a/src/journal/test-compress-benchmark.c b/src/journal/test-compress-benchmark.c
index c8e5b76c6c..0be6820a14 100644
--- a/src/journal/test-compress-benchmark.c
+++ b/src/journal/test-compress-benchmark.c
@@ -20,6 +20,7 @@
#include "compress.h"
#include "util.h"
#include "macro.h"
+#include "random-util.h"
typedef int (compress_t)(const void *src, uint64_t src_size, void *dst, size_t *dst_size);
typedef int (decompress_t)(const void *src, uint64_t src_size,
@@ -27,20 +28,31 @@ typedef int (decompress_t)(const void *src, uint64_t src_size,
#define MAX_SIZE (1024*1024LU)
-static char* make_buf(size_t count) {
+static char* make_buf(size_t count, const char *type) {
char *buf;
size_t i;
buf = malloc(count);
assert_se(buf);
- for (i = 0; i < count; i++)
- buf[i] = 'a' + i % ('z' - 'a' + 1);
+ if (streq(type, "zeros"))
+ memzero(buf, count);
+ else if (streq(type, "simple"))
+ for (i = 0; i < count; i++)
+ buf[i] = 'a' + i % ('z' - 'a' + 1);
+ else if (streq(type, "random")) {
+ random_bytes(buf, count/10);
+ random_bytes(buf + 2*count/10, count/10);
+ random_bytes(buf + 4*count/10, count/20);
+ random_bytes(buf + 6*count/10, count/20);
+ random_bytes(buf + 8*count/10, count/20);
+ } else
+ assert_not_reached("here");
return buf;
}
-static void test_compress_decompress(const char* label,
+static void test_compress_decompress(const char* label, const char* type,
compress_t compress, decompress_t decompress) {
usec_t n, n2 = 0;
float dt;
@@ -50,7 +62,7 @@ static void test_compress_decompress(const char* label,
size_t buf2_allocated = 0;
size_t skipped = 0, compressed = 0, total = 0;
- text = make_buf(MAX_SIZE);
+ text = make_buf(MAX_SIZE, type);
buf = calloc(MAX_SIZE + 1, 1);
assert_se(text && buf);
@@ -62,7 +74,8 @@ static void test_compress_decompress(const char* label,
r = compress(text, i, buf, &j);
/* assume compression must be successful except for small inputs */
- assert_se(r == 0 || (i < 2048 && r == -ENOBUFS));
+ assert_se(r == 0 || (i < 2048 && r == -ENOBUFS) || streq(type, "random"));
+
/* check for overwrites */
assert_se(buf[i] == 0);
if (r != 0) {
@@ -91,23 +104,26 @@ static void test_compress_decompress(const char* label,
dt = (n2-n) / 1e6;
- log_info("%s: compressed & decompressed %zu bytes in %.2fs (%.2fMiB/s), "
+ log_info("%s/%s: compressed & decompressed %zu bytes in %.2fs (%.2fMiB/s), "
"mean compresion %.2f%%, skipped %zu bytes",
- label, total, dt,
+ label, type, total, dt,
total / 1024. / 1024 / dt,
100 - compressed * 100. / total,
skipped);
}
int main(int argc, char *argv[]) {
+ const char *i;
log_set_max_level(LOG_DEBUG);
+ NULSTR_FOREACH(i, "zeros\0simple\0random\0") {
#ifdef HAVE_XZ
- test_compress_decompress("XZ", compress_blob_xz, decompress_blob_xz);
+ test_compress_decompress("XZ", i, compress_blob_xz, decompress_blob_xz);
#endif
#ifdef HAVE_LZ4
- test_compress_decompress("LZ4", compress_blob_lz4, decompress_blob_lz4);
+ test_compress_decompress("LZ4", i, compress_blob_lz4, decompress_blob_lz4);
#endif
+ }
return 0;
}
diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c
index f17c00e60d..e51b12407f 100644
--- a/src/journal/test-compress.c
+++ b/src/journal/test-compress.c
@@ -144,8 +144,8 @@ static void test_compress_stream(int compression,
const char *srcfile) {
_cleanup_close_ int src = -1, dst = -1, dst2 = -1;
- char pattern[] = "/tmp/systemd-test.xz.XXXXXX",
- pattern2[] = "/tmp/systemd-test.xz.XXXXXX";
+ char pattern[] = "/tmp/systemd-test.compressed.XXXXXX",
+ pattern2[] = "/tmp/systemd-test.compressed.XXXXXX";
int r;
_cleanup_free_ char *cmd = NULL, *cmd2;
struct stat st = {};
@@ -185,7 +185,7 @@ static void test_compress_stream(int compression,
assert_se(lseek(dst, 1, SEEK_SET) == 1);
r = decompress(dst, dst2, st.st_size);
- assert_se(r == -EBADMSG);
+ assert_se(r == -EBADMSG || r == 0);
assert_se(lseek(dst, 0, SEEK_SET) == 0);
assert_se(lseek(dst2, 0, SEEK_SET) == 0);
@@ -236,8 +236,7 @@ int main(int argc, char *argv[]) {
compress_blob_lz4, decompress_startswith_lz4,
data, sizeof(data), true);
- /* Produced stream is not compatible with lz4 binary, skip lz4cat check. */
- test_compress_stream(OBJECT_COMPRESSED_LZ4, NULL,
+ test_compress_stream(OBJECT_COMPRESSED_LZ4, "lz4cat",
compress_stream_lz4, decompress_stream_lz4, argv[0]);
#else
log_info("/* LZ4 test skipped */");
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 141b836a0d..28e012afca 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -1265,8 +1265,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
return r;
log_dhcp_client(client, "lease expires in %s",
- format_timespan(time_string, FORMAT_TIMESPAN_MAX,
- lifetime_timeout - time_now, 0));
+ format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_timeout - time_now, USEC_PER_SEC));
/* don't arm earlier timeouts if this has already expired */
if (lifetime_timeout <= time_now)
@@ -1292,8 +1291,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
return r;
log_dhcp_client(client, "T2 expires in %s",
- format_timespan(time_string, FORMAT_TIMESPAN_MAX,
- t2_timeout - time_now, 0));
+ format_timespan(time_string, FORMAT_TIMESPAN_MAX, t2_timeout - time_now, USEC_PER_SEC));
/* don't arm earlier timeout if this has already expired */
if (t2_timeout <= time_now)
@@ -1318,8 +1316,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
return r;
log_dhcp_client(client, "T1 expires in %s",
- format_timespan(time_string, FORMAT_TIMESPAN_MAX,
- t1_timeout - time_now, 0));
+ format_timespan(time_string, FORMAT_TIMESPAN_MAX, t1_timeout - time_now, USEC_PER_SEC));
return 0;
}
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index acb31a16c2..9cd4bd3032 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -595,8 +595,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
}
log_dhcp6_client(client, "Next retransmission in %s",
- format_timespan(time_string, FORMAT_TIMESPAN_MAX,
- client->retransmit_time, 0));
+ format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->retransmit_time, USEC_PER_SEC));
r = sd_event_add_time(client->event, &client->timeout_resend,
clock_boottime_or_monotonic(),
@@ -1048,9 +1047,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t1) * USEC_PER_SEC);
log_dhcp6_client(client, "T1 expires in %s",
- format_timespan(time_string,
- FORMAT_TIMESPAN_MAX,
- timeout, 0));
+ format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
r = sd_event_add_time(client->event,
&client->lease->ia.timeout_t1,
@@ -1072,9 +1069,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t2) * USEC_PER_SEC);
log_dhcp6_client(client, "T2 expires in %s",
- format_timespan(time_string,
- FORMAT_TIMESPAN_MAX,
- timeout, 0));
+ format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
r = sd_event_add_time(client->event,
&client->lease->ia.timeout_t2,
diff --git a/src/libsystemd-network/sd-icmp6-nd.c b/src/libsystemd-network/sd-icmp6-nd.c
index bedcac8d9e..f014cac628 100644
--- a/src/libsystemd-network/sd-icmp6-nd.c
+++ b/src/libsystemd-network/sd-icmp6-nd.c
@@ -444,8 +444,7 @@ static int icmp6_ra_prefix_update(sd_icmp6_nd *nd, ssize_t len,
log_icmp6_nd(nd, "New prefix "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
SD_ICMP6_ND_ADDRESS_FORMAT_VAL(prefix->addr),
prefix->len, lifetime,
- format_timespan(time_string, FORMAT_TIMESPAN_MAX,
- lifetime * USEC_PER_SEC, 0));
+ format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime * USEC_PER_SEC, USEC_PER_SEC));
LIST_PREPEND(prefixes, nd->prefixes, prefix);
@@ -466,8 +465,7 @@ static int icmp6_ra_prefix_update(sd_icmp6_nd *nd, ssize_t len,
log_icmp6_nd(nd, "Update prefix "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
SD_ICMP6_ND_ADDRESS_FORMAT_VAL(prefix->addr),
prefix->len, lifetime,
- format_timespan(time_string, FORMAT_TIMESPAN_MAX,
- lifetime * USEC_PER_SEC, 0));
+ format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime * USEC_PER_SEC, USEC_PER_SEC));
}
r = icmp6_ra_prefix_set_timeout(nd, prefix, lifetime * USEC_PER_SEC);
diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c
index dd427ddd78..57bd337a9a 100644
--- a/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/libsystemd-network/sd-ipv4ll.c
@@ -25,6 +25,7 @@
#include <arpa/inet.h>
#include "event-util.h"
+#include "in-addr-util.h"
#include "list.h"
#include "random-util.h"
#include "refcnt.h"
@@ -232,6 +233,39 @@ bool sd_ipv4ll_is_running(sd_ipv4ll *ll) {
return sd_ipv4acd_is_running(ll->acd);
}
+static bool ipv4ll_address_is_valid(const struct in_addr *address) {
+ uint32_t addr;
+
+ assert(address);
+
+ if (!in_addr_is_link_local(AF_INET, (const union in_addr_union *) address))
+ return false;
+
+ addr = be32toh(address->s_addr);
+
+ if ((addr & 0x0000FF00) == 0x0000 ||
+ (addr & 0x0000FF00) == 0xFF00)
+ return false;
+
+ return true;
+}
+
+int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) {
+ int r;
+
+ assert_return(ll, -EINVAL);
+ assert_return(address, -EINVAL);
+ assert_return(ipv4ll_address_is_valid(address), -EINVAL);
+
+ r = sd_ipv4acd_set_address(ll->acd, address);
+ if (r < 0)
+ return r;
+
+ ll->address = address->s_addr;
+
+ return 0;
+}
+
static int ipv4ll_pick_address(sd_ipv4ll *ll) {
struct in_addr in_addr;
be32_t addr;
@@ -247,18 +281,15 @@ static int ipv4ll_pick_address(sd_ipv4ll *ll) {
return r;
addr = htonl((random & 0x0000FFFF) | IPV4LL_NETWORK);
} while (addr == ll->address ||
- (ntohl(addr) & IPV4LL_NETMASK) != IPV4LL_NETWORK ||
(ntohl(addr) & 0x0000FF00) == 0x0000 ||
(ntohl(addr) & 0x0000FF00) == 0xFF00);
in_addr.s_addr = addr;
- r = sd_ipv4acd_set_address(ll->acd, &in_addr);
+ r = sd_ipv4ll_set_address(ll, &in_addr);
if (r < 0)
return r;
- ll->address = addr;
-
return 0;
}
diff --git a/src/libsystemd-network/test-ipv4ll.c b/src/libsystemd-network/test-ipv4ll.c
index e72204d992..b67a9f17d7 100644
--- a/src/libsystemd-network/test-ipv4ll.c
+++ b/src/libsystemd-network/test-ipv4ll.c
@@ -100,6 +100,7 @@ int arp_network_bind_raw_socket(int index, be32_t address, const struct ether_ad
}
static void test_public_api_setters(sd_event *e) {
+ struct in_addr address = {};
unsigned seed = 0;
sd_ipv4ll *ll;
struct ether_addr mac_addr = {
@@ -118,6 +119,16 @@ static void test_public_api_setters(sd_event *e) {
assert_se(sd_ipv4ll_set_callback(NULL, NULL, NULL) == -EINVAL);
assert_se(sd_ipv4ll_set_callback(ll, NULL, NULL) == 0);
+ assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
+ address.s_addr |= htobe32(169U << 24 | 254U << 16);
+ assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
+ address.s_addr |= htobe32(0x00FF);
+ assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
+ address.s_addr |= htobe32(0xF000);
+ assert_se(sd_ipv4ll_set_address(ll, &address) == 0);
+ address.s_addr |= htobe32(0x0F00);
+ assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
+
assert_se(sd_ipv4ll_set_address_seed(NULL, seed) == -EINVAL);
assert_se(sd_ipv4ll_set_address_seed(ll, seed) == 0);
diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c
index 437518119b..ae534ba5b9 100644
--- a/src/libsystemd/sd-daemon/sd-daemon.c
+++ b/src/libsystemd/sd-daemon/sd-daemon.c
@@ -450,9 +450,11 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
if (n_fds > 0 || have_pid) {
/* CMSG_SPACE(0) may return value different then zero, which results in miscalculated controllen. */
- msghdr.msg_controllen = (n_fds ? CMSG_SPACE(sizeof(int) * n_fds) : 0) +
- CMSG_SPACE(sizeof(struct ucred)) * have_pid;
- msghdr.msg_control = alloca(msghdr.msg_controllen);
+ msghdr.msg_controllen =
+ (n_fds > 0 ? CMSG_SPACE(sizeof(int) * n_fds) : 0) +
+ (have_pid ? CMSG_SPACE(sizeof(struct ucred)) : 0);
+
+ msghdr.msg_control = alloca0(msghdr.msg_controllen);
cmsg = CMSG_FIRSTHDR(&msghdr);
if (n_fds > 0) {
diff --git a/src/libsystemd/sd-netlink/netlink-internal.h b/src/libsystemd/sd-netlink/netlink-internal.h
index 4026e2c341..b9cb80668d 100644
--- a/src/libsystemd/sd-netlink/netlink-internal.h
+++ b/src/libsystemd/sd-netlink/netlink-internal.h
@@ -64,6 +64,9 @@ struct sd_netlink {
struct sockaddr_nl nl;
} sockaddr;
+ Hashmap *broadcast_group_refs;
+ bool broadcast_group_dont_leave:1; /* until we can rely on 4.2 */
+
sd_netlink_message **rqueue;
unsigned rqueue_size;
size_t rqueue_allocated;
@@ -124,7 +127,8 @@ int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret);
int socket_open(int family);
int socket_bind(sd_netlink *nl);
-int socket_join_broadcast_group(sd_netlink *nl, unsigned group);
+int socket_broadcast_group_ref(sd_netlink *nl, unsigned group);
+int socket_broadcast_group_unref(sd_netlink *nl, unsigned group);
int socket_write_message(sd_netlink *nl, sd_netlink_message *m);
int socket_read_message(sd_netlink *nl);
diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c
index 84ff7c38c9..e1b14c3ed2 100644
--- a/src/libsystemd/sd-netlink/netlink-socket.c
+++ b/src/libsystemd/sd-netlink/netlink-socket.c
@@ -44,6 +44,65 @@ int socket_open(int family) {
return fd;
}
+static int broadcast_groups_get(sd_netlink *nl) {
+ _cleanup_free_ uint32_t *groups = NULL;
+ socklen_t len = 0, old_len;
+ unsigned i, j;
+ int r;
+
+ assert(nl);
+ assert(nl->fd > 0);
+
+ r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len);
+ if (r < 0) {
+ if (errno == ENOPROTOOPT) {
+ nl->broadcast_group_dont_leave = true;
+ return 0;
+ } else
+ return -errno;
+ }
+
+ if (len == 0)
+ return 0;
+
+ groups = new0(uint32_t, len);
+ if (!groups)
+ return -ENOMEM;
+
+ old_len = len;
+
+ r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, groups, &len);
+ if (r < 0)
+ return -errno;
+
+ if (old_len != len)
+ return -EIO;
+
+ r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL);
+ if (r < 0)
+ return r;
+
+ for (i = 0; i < len; i++) {
+ for (j = 0; j < sizeof(uint32_t) * 8; j ++) {
+ uint32_t offset;
+ unsigned group;
+
+ offset = 1U << j;
+
+ if (!(groups[i] & offset))
+ continue;
+
+ group = i * sizeof(uint32_t) * 8 + j + 1;
+
+ r = hashmap_put(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(1));
+ if (r < 0)
+ return r;
+ }
+ }
+
+ return 0;
+}
+
int socket_bind(sd_netlink *nl) {
socklen_t addrlen;
int r, one = 1;
@@ -63,11 +122,32 @@ int socket_bind(sd_netlink *nl) {
if (r < 0)
return -errno;
+ r = broadcast_groups_get(nl);
+ if (r < 0)
+ return r;
+
return 0;
}
+static unsigned broadcast_group_get_ref(sd_netlink *nl, unsigned group) {
+ assert(nl);
+
+ return PTR_TO_UINT(hashmap_get(nl->broadcast_group_refs, UINT_TO_PTR(group)));
+}
-int socket_join_broadcast_group(sd_netlink *nl, unsigned group) {
+static int broadcast_group_set_ref(sd_netlink *nl, unsigned group, unsigned n_ref) {
+ int r;
+
+ assert(nl);
+
+ r = hashmap_replace(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(n_ref));
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int broadcast_group_join(sd_netlink *nl, unsigned group) {
int r;
assert(nl);
@@ -81,6 +161,79 @@ int socket_join_broadcast_group(sd_netlink *nl, unsigned group) {
return 0;
}
+int socket_broadcast_group_ref(sd_netlink *nl, unsigned group) {
+ unsigned n_ref;
+ int r;
+
+ assert(nl);
+
+ n_ref = broadcast_group_get_ref(nl, group);
+
+ n_ref ++;
+
+ r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL);
+ if (r < 0)
+ return r;
+
+ r = broadcast_group_set_ref(nl, group, n_ref);
+ if (r < 0)
+ return r;
+
+ if (n_ref > 1)
+ /* not yet in the group */
+ return 0;
+
+ r = broadcast_group_join(nl, group);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int broadcast_group_leave(sd_netlink *nl, unsigned group) {
+ int r;
+
+ assert(nl);
+ assert(nl->fd >= 0);
+ assert(group > 0);
+
+ if (nl->broadcast_group_dont_leave)
+ return 0;
+
+ r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, &group, sizeof(group));
+ if (r < 0)
+ return -errno;
+
+ return 0;
+}
+
+int socket_broadcast_group_unref(sd_netlink *nl, unsigned group) {
+ unsigned n_ref;
+ int r;
+
+ assert(nl);
+
+ n_ref = broadcast_group_get_ref(nl, group);
+
+ assert(n_ref > 0);
+
+ n_ref --;
+
+ r = broadcast_group_set_ref(nl, group, n_ref);
+ if (r < 0)
+ return r;
+
+ if (n_ref > 0)
+ /* still refs left */
+ return 0;
+
+ r = broadcast_group_leave(nl, group);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
/* returns the number of bytes sent, or a negative error code */
int socket_write_message(sd_netlink *nl, sd_netlink_message *m) {
union {
diff --git a/src/libsystemd/sd-netlink/rtnl-message.c b/src/libsystemd/sd-netlink/rtnl-message.c
index 2f31f4ee69..03049bd31f 100644
--- a/src/libsystemd/sd-netlink/rtnl-message.c
+++ b/src/libsystemd/sd-netlink/rtnl-message.c
@@ -99,6 +99,66 @@ int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family) {
return 0;
}
+int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol) {
+ struct rtmsg *rtm;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
+ assert_return(protocol, -EINVAL);
+
+ rtm = NLMSG_DATA(m->hdr);
+
+ *protocol = rtm->rtm_protocol;
+
+ return 0;
+}
+
+int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope) {
+ struct rtmsg *rtm;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
+ assert_return(scope, -EINVAL);
+
+ rtm = NLMSG_DATA(m->hdr);
+
+ *scope = rtm->rtm_scope;
+
+ return 0;
+}
+
+int sd_rtnl_message_route_get_tos(sd_netlink_message *m, unsigned char *tos) {
+ struct rtmsg *rtm;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
+ assert_return(tos, -EINVAL);
+
+ rtm = NLMSG_DATA(m->hdr);
+
+ *tos = rtm->rtm_tos;
+
+ return 0;
+}
+
+int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table) {
+ struct rtmsg *rtm;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
+ assert_return(table, -EINVAL);
+
+ rtm = NLMSG_DATA(m->hdr);
+
+ *table = rtm->rtm_table;
+
+ return 0;
+}
+
int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len) {
struct rtmsg *rtm;
diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c
index d248869c8d..5af28600ba 100644
--- a/src/libsystemd/sd-netlink/sd-netlink.c
+++ b/src/libsystemd/sd-netlink/sd-netlink.c
@@ -183,10 +183,11 @@ sd_netlink *sd_netlink_unref(sd_netlink *rtnl) {
sd_event_unref(rtnl->event);
while ((f = rtnl->match_callbacks)) {
- LIST_REMOVE(match_callbacks, rtnl->match_callbacks, f);
- free(f);
+ sd_netlink_remove_match(rtnl, f->type, f->callback, f->userdata);
}
+ hashmap_free(rtnl->broadcast_group_refs);
+
safe_close(rtnl->fd);
free(rtnl);
}
@@ -856,25 +857,32 @@ int sd_netlink_add_match(sd_netlink *rtnl,
switch (type) {
case RTM_NEWLINK:
- case RTM_SETLINK:
- case RTM_GETLINK:
case RTM_DELLINK:
- r = socket_join_broadcast_group(rtnl, RTNLGRP_LINK);
+ r = socket_broadcast_group_ref(rtnl, RTNLGRP_LINK);
if (r < 0)
return r;
break;
case RTM_NEWADDR:
- case RTM_GETADDR:
case RTM_DELADDR:
- r = socket_join_broadcast_group(rtnl, RTNLGRP_IPV4_IFADDR);
+ r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_IFADDR);
if (r < 0)
return r;
- r = socket_join_broadcast_group(rtnl, RTNLGRP_IPV6_IFADDR);
+ r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_IFADDR);
+ if (r < 0)
+ return r;
+
+ break;
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_ROUTE);
if (r < 0)
return r;
+ r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_ROUTE);
+ if (r < 0)
+ return r;
break;
default:
return -EOPNOTSUPP;
@@ -892,23 +900,50 @@ int sd_netlink_remove_match(sd_netlink *rtnl,
sd_netlink_message_handler_t callback,
void *userdata) {
struct match_callback *c;
+ int r;
assert_return(rtnl, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
- /* we should unsubscribe from the broadcast groups at this point, but it is not so
- trivial for a few reasons: the refcounting is a bit of a mess and not obvious
- how it will look like after we add genetlink support, and it is also not possible
- to query what broadcast groups were subscribed to when we inherit the socket to get
- the initial refcount. The latter could indeed be done for the first 32 broadcast
- groups (which incidentally is all we currently support in .socket units anyway),
- but we better not rely on only ever using 32 groups. */
LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks)
if (c->callback == callback && c->type == type && c->userdata == userdata) {
LIST_REMOVE(match_callbacks, rtnl->match_callbacks, c);
free(c);
+ switch (type) {
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ r = socket_broadcast_group_unref(rtnl, RTNLGRP_LINK);
+ if (r < 0)
+ return r;
+
+ break;
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV4_IFADDR);
+ if (r < 0)
+ return r;
+
+ r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV6_IFADDR);
+ if (r < 0)
+ return r;
+
+ break;
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV4_ROUTE);
+ if (r < 0)
+ return r;
+
+ r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV6_ROUTE);
+ if (r < 0)
+ return r;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
return 1;
}
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 40d587ddb8..aeedf68e77 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -2588,7 +2588,7 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
}
if (m->action_job && streq(m->action_job, path)) {
- log_info("Operation finished.");
+ log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
/* Tell people that they now may take a lock again */
send_prepare_for(m, m->action_what, false);
diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c
index d609daafde..b3450c1456 100644
--- a/src/network/networkd-address-pool.c
+++ b/src/network/networkd-address-pool.c
@@ -21,6 +21,7 @@
#include "networkd.h"
#include "networkd-address-pool.h"
+#include "set.h"
int address_pool_new(
Manager *m,
@@ -96,9 +97,10 @@ static bool address_pool_prefix_is_taken(
HASHMAP_FOREACH(l, p->manager->links, i) {
Address *a;
+ Iterator j;
/* Don't clash with assigned addresses */
- LIST_FOREACH(addresses, a, l->addresses) {
+ SET_FOREACH(a, l->addresses, j) {
if (a->family != p->family)
continue;
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 388beb5d4c..316ae2e4cb 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -21,26 +21,37 @@
#include <net/if.h>
-#include "utf8.h"
-#include "util.h"
#include "conf-parser.h"
#include "firewall-util.h"
#include "netlink-util.h"
+#include "set.h"
+#include "utf8.h"
+#include "util.h"
#include "networkd.h"
#include "networkd-address.h"
-static void address_init(Address *address) {
- assert(address);
+int address_new(Address **ret) {
+ _cleanup_address_free_ Address *address = NULL;
+
+ address = new0(Address, 1);
+ if (!address)
+ return -ENOMEM;
address->family = AF_UNSPEC;
address->scope = RT_SCOPE_UNIVERSE;
address->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME;
address->cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME;
+
+ *ret = address;
+ address = NULL;
+
+ return 0;
}
int address_new_static(Network *network, unsigned section, Address **ret) {
_cleanup_address_free_ Address *address = NULL;
+ int r;
if (section) {
address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section));
@@ -52,11 +63,9 @@ int address_new_static(Network *network, unsigned section, Address **ret) {
}
}
- address = new0(Address, 1);
- if (!address)
- return -ENOMEM;
-
- address_init(address);
+ r = address_new(&address);
+ if (r < 0)
+ return r;
address->network = network;
@@ -74,21 +83,6 @@ int address_new_static(Network *network, unsigned section, Address **ret) {
return 0;
}
-int address_new_dynamic(Address **ret) {
- _cleanup_address_free_ Address *address = NULL;
-
- address = new0(Address, 1);
- if (!address)
- return -ENOMEM;
-
- address_init(address);
-
- *ret = address;
- address = NULL;
-
- return 0;
-}
-
void address_free(Address *address) {
if (!address)
return;
@@ -101,10 +95,110 @@ void address_free(Address *address) {
UINT_TO_PTR(address->section));
}
+ if (address->link)
+ set_remove(address->link->addresses, address);
+
free(address);
}
-int address_establish(Address *address, Link *link) {
+static void address_hash_func(const void *b, struct siphash *state) {
+ const Address *a = b;
+
+ assert(a);
+
+ siphash24_compress(&a->family, sizeof(a->family), state);
+
+ switch (a->family) {
+ case AF_INET:
+ siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
+
+ /* peer prefix */
+ if (a->prefixlen != 0) {
+ uint32_t prefix;
+
+ if (a->in_addr_peer.in.s_addr != 0)
+ prefix = be32toh(a->in_addr_peer.in.s_addr) >> (32 - a->prefixlen);
+ else
+ prefix = be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen);
+
+ siphash24_compress(&prefix, sizeof(prefix), state);
+ }
+
+ /* fallthrough */
+ case AF_INET6:
+ /* local address */
+ siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state);
+
+ break;
+ default:
+ /* treat any other address family as AF_UNSPEC */
+ break;
+ }
+}
+
+static int address_compare_func(const void *c1, const void *c2) {
+ const Address *a1 = c1, *a2 = c2;
+
+ if (a1->family < a2->family)
+ return -1;
+ if (a1->family > a2->family)
+ return 1;
+
+ switch (a1->family) {
+ /* use the same notion of equality as the kernel does */
+ case AF_INET:
+ if (a1->prefixlen < a2->prefixlen)
+ return -1;
+ if (a1->prefixlen > a2->prefixlen)
+ return 1;
+
+ /* compare the peer prefixes */
+ if (a1->prefixlen != 0) {
+ /* make sure we don't try to shift by 32.
+ * See ISO/IEC 9899:TC3 § 6.5.7.3. */
+ uint32_t b1, b2;
+
+ if (a1->in_addr_peer.in.s_addr != 0)
+ b1 = be32toh(a1->in_addr_peer.in.s_addr) >> (32 - a1->prefixlen);
+ else
+ b1 = be32toh(a1->in_addr.in.s_addr) >> (32 - a1->prefixlen);
+
+ if (a2->in_addr_peer.in.s_addr != 0)
+ b2 = be32toh(a2->in_addr_peer.in.s_addr) >> (32 - a1->prefixlen);
+ else
+ b2 = be32toh(a2->in_addr.in.s_addr) >> (32 - a1->prefixlen);
+
+ if (b1 < b2)
+ return -1;
+ if (b1 > b2)
+ return 1;
+ }
+
+ /* fall-through */
+ case AF_INET6:
+ return memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family));
+ default:
+ /* treat any other address family as AF_UNSPEC */
+ return 0;
+ }
+}
+
+static const struct hash_ops address_hash_ops = {
+ .hash = address_hash_func,
+ .compare = address_compare_func
+};
+
+bool address_equal(Address *a1, Address *a2) {
+ if (a1 == a2)
+ return true;
+
+ if (!a1 || !a2)
+ return false;
+
+ return address_compare_func(a1, a2) == 0;
+}
+
+static int address_establish(Address *address, Link *link) {
bool masq;
int r;
@@ -131,7 +225,43 @@ int address_establish(Address *address, Link *link) {
return 0;
}
-int address_release(Address *address, Link *link) {
+int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
+ _cleanup_address_free_ Address *address = NULL;
+ int r;
+
+ assert(link);
+ assert(in_addr);
+ assert(ret);
+
+ r = address_new(&address);
+ if (r < 0)
+ return r;
+
+ address->family = family;
+ address->in_addr = *in_addr;
+ address->prefixlen = prefixlen;
+
+ r = set_ensure_allocated(&link->addresses, &address_hash_ops);
+ if (r < 0)
+ return r;
+
+ r = set_put(link->addresses, address);
+ if (r < 0)
+ return r;
+
+ address->link = link;
+
+ r = address_establish(address, link);
+ if (r < 0)
+ return r;
+
+ *ret = address;
+ address = NULL;
+
+ return 0;
+}
+
+static int address_release(Address *address, Link *link) {
int r;
assert(address);
@@ -152,7 +282,36 @@ int address_release(Address *address, Link *link) {
return 0;
}
-int address_drop(Address *address, Link *link,
+int address_drop(Address *address) {
+ assert(address);
+
+ address_release(address, address->link);
+ address_free(address);
+
+ return 0;
+}
+
+int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
+ Address address = {}, *existing;
+
+ assert(link);
+ assert(in_addr);
+ assert(ret);
+
+ address.family = family;
+ address.in_addr = *in_addr;
+ address.prefixlen = prefixlen;
+
+ existing = set_get(link->addresses, &address);
+ if (!existing)
+ return -ENOENT;
+
+ *ret = existing;
+
+ return 0;
+}
+
+int address_remove(Address *address, Link *link,
sd_netlink_message_handler_t callback) {
_cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
int r;
@@ -292,7 +451,7 @@ static int address_acquire(Link *link, Address *original, Address **ret) {
} else if (original->family == AF_INET6)
in_addr.in6.s6_addr[15] |= 1;
- r = address_new_dynamic(&na);
+ r = address_new(&na);
if (r < 0)
return r;
@@ -580,49 +739,8 @@ int config_parse_label(const char *unit,
return 0;
}
-bool address_equal(Address *a1, Address *a2) {
- /* same object */
- if (a1 == a2)
- return true;
-
- /* one, but not both, is NULL */
- if (!a1 || !a2)
- return false;
-
- if (a1->family != a2->family)
- return false;
-
- switch (a1->family) {
- /* use the same notion of equality as the kernel does */
- case AF_UNSPEC:
- return true;
-
- case AF_INET:
- if (a1->prefixlen != a2->prefixlen)
- return false;
- else if (a1->prefixlen == 0)
- /* make sure we don't try to shift by 32.
- * See ISO/IEC 9899:TC3 § 6.5.7.3. */
- return true;
- else {
- uint32_t b1, b2;
-
- b1 = be32toh(a1->in_addr.in.s_addr);
- b2 = be32toh(a2->in_addr.in.s_addr);
-
- return (b1 >> (32 - a1->prefixlen)) == (b2 >> (32 - a1->prefixlen));
- }
-
- case AF_INET6: {
- uint64_t *b1, *b2;
-
- b1 = (uint64_t*)&a1->in_addr.in6;
- b2 = (uint64_t*)&a2->in_addr.in6;
+bool address_is_ready(const Address *a) {
+ assert(a);
- return (((b1[0] ^ b2[0]) | (b1[1] ^ b2[1])) == 0UL);
- }
-
- default:
- assert_not_reached("Invalid address family");
- }
+ return !(a->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED));
}
diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h
index 39789a2382..425344fe48 100644
--- a/src/network/networkd-address.h
+++ b/src/network/networkd-address.h
@@ -38,6 +38,8 @@ struct Address {
Network *network;
unsigned section;
+ Link *link;
+
int family;
unsigned char prefixlen;
unsigned char scope;
@@ -56,14 +58,16 @@ struct Address {
};
int address_new_static(Network *network, unsigned section, Address **ret);
-int address_new_dynamic(Address **ret);
+int address_new(Address **ret);
void address_free(Address *address);
+int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
+int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
+int address_drop(Address *address);
int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback);
int address_update(Address *address, Link *link, sd_netlink_message_handler_t callback);
-int address_drop(Address *address, Link *link, sd_netlink_message_handler_t callback);
-int address_establish(Address *address, Link *link);
-int address_release(Address *address, Link *link);
+int address_remove(Address *address, Link *link, sd_netlink_message_handler_t callback);
bool address_equal(Address *a1, Address *a2);
+bool address_is_ready(const Address *a);
DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free);
#define _cleanup_address_free_ _cleanup_(address_freep)
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 04f04df117..5d9bfcea7c 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -72,11 +72,11 @@ static int link_set_dhcp_routes(Link *link) {
if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
- r = route_new_dynamic(&route, RTPROT_DHCP);
+ r = route_new(&route, RTPROT_DHCP);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate route: %m");
- r = route_new_dynamic(&route_gw, RTPROT_DHCP);
+ r = route_new(&route_gw, RTPROT_DHCP);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate route: %m");
@@ -120,7 +120,7 @@ static int link_set_dhcp_routes(Link *link) {
for (i = 0; i < n; i++) {
_cleanup_route_free_ Route *route = NULL;
- r = route_new_dynamic(&route, RTPROT_DHCP);
+ r = route_new(&route, RTPROT_DHCP);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate route: %m");
@@ -162,45 +162,45 @@ static int dhcp_lease_lost(Link *link) {
for (i = 0; i < n; i++) {
_cleanup_route_free_ Route *route = NULL;
- r = route_new_dynamic(&route, RTPROT_UNSPEC);
+ r = route_new(&route, RTPROT_UNSPEC);
if (r >= 0) {
route->family = AF_INET;
route->in_addr.in = routes[i].gw_addr;
route->dst_addr.in = routes[i].dst_addr;
route->dst_prefixlen = routes[i].dst_prefixlen;
- route_drop(route, link,
- &link_route_drop_handler);
+ route_remove(route, link,
+ &link_route_remove_handler);
}
}
}
}
- r = address_new_dynamic(&address);
+ r = address_new(&address);
if (r >= 0) {
r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
if (r >= 0) {
_cleanup_route_free_ Route *route_gw = NULL;
_cleanup_route_free_ Route *route = NULL;
- r = route_new_dynamic(&route_gw, RTPROT_UNSPEC);
+ r = route_new(&route_gw, RTPROT_UNSPEC);
if (r >= 0) {
route_gw->family = AF_INET;
route_gw->dst_addr.in = gateway;
route_gw->dst_prefixlen = 32;
route_gw->scope = RT_SCOPE_LINK;
- route_drop(route_gw, link,
- &link_route_drop_handler);
+ route_remove(route_gw, link,
+ &link_route_remove_handler);
}
- r = route_new_dynamic(&route, RTPROT_UNSPEC);
+ r = route_new(&route, RTPROT_UNSPEC);
if (r >= 0) {
route->family = AF_INET;
route->in_addr.in = gateway;
- route_drop(route, link,
- &link_route_drop_handler);
+ route_remove(route, link,
+ &link_route_remove_handler);
}
}
@@ -214,7 +214,7 @@ static int dhcp_lease_lost(Link *link) {
address->in_addr.in = addr;
address->prefixlen = prefixlen;
- address_drop(address, link, &link_address_drop_handler);
+ address_remove(address, link, &link_address_remove_handler);
}
}
@@ -267,7 +267,7 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
log_link_error_errno(link, r, "Could not set DHCPv4 address: %m");
link_enter_failed(link);
} else if (r >= 0)
- link_rtnl_process_address(rtnl, m, link->manager);
+ manager_rtnl_process_address(rtnl, m, link->manager);
link_set_dhcp_routes(link);
@@ -288,7 +288,7 @@ static int dhcp4_update_address(Link *link,
prefixlen = in_addr_netmask_to_prefixlen(netmask);
- r = address_new_dynamic(&addr);
+ r = address_new(&addr);
if (r < 0)
return r;
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index 3cb7b8d9ca..2f9ecf7a89 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -58,7 +58,7 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
link_enter_failed(link);
} else if (r >= 0)
- link_rtnl_process_address(rtnl, m, link->manager);
+ manager_rtnl_process_address(rtnl, m, link->manager);
return 1;
}
@@ -69,7 +69,7 @@ static int dhcp6_address_update(Link *link, struct in6_addr *ip6_addr,
int r;
_cleanup_address_free_ Address *addr = NULL;
- r = address_new_dynamic(&addr);
+ r = address_new(&addr);
if (r < 0)
return r;
diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c
index 1902b3d23a..01ee9f9f4a 100644
--- a/src/network/networkd-ipv4ll.c
+++ b/src/network/networkd-ipv4ll.c
@@ -42,7 +42,7 @@ static int ipv4ll_address_lost(Link *link) {
log_link_debug(link, "IPv4 link-local release %u.%u.%u.%u", ADDRESS_FMT_VAL(addr));
- r = address_new_dynamic(&address);
+ r = address_new(&address);
if (r < 0) {
log_link_error_errno(link, r, "Could not allocate address: %m");
return r;
@@ -53,9 +53,9 @@ static int ipv4ll_address_lost(Link *link) {
address->prefixlen = 16;
address->scope = RT_SCOPE_LINK;
- address_drop(address, link, &link_address_drop_handler);
+ address_remove(address, link, &link_address_remove_handler);
- r = route_new_dynamic(&route, RTPROT_UNSPEC);
+ r = route_new(&route, RTPROT_UNSPEC);
if (r < 0) {
log_link_error_errno(link, r, "Could not allocate route: %m");
return r;
@@ -65,7 +65,7 @@ static int ipv4ll_address_lost(Link *link) {
route->scope = RT_SCOPE_LINK;
route->metrics = IPV4LL_ROUTE_METRIC;
- route_drop(route, link, &link_route_drop_handler);
+ route_remove(route, link, &link_route_remove_handler);
link_client_handler(link);
@@ -105,7 +105,7 @@ static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void
log_link_error_errno(link, r, "could not set ipv4ll address: %m");
link_enter_failed(link);
} else if (r >= 0)
- link_rtnl_process_address(rtnl, m, link->manager);
+ manager_rtnl_process_address(rtnl, m, link->manager);
link->ipv4ll_address = true;
@@ -133,7 +133,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
log_link_debug(link, "IPv4 link-local claim %u.%u.%u.%u",
ADDRESS_FMT_VAL(address));
- r = address_new_dynamic(&ll_addr);
+ r = address_new(&ll_addr);
if (r < 0)
return r;
@@ -149,7 +149,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
link->ipv4ll_address = false;
- r = route_new_dynamic(&route, RTPROT_STATIC);
+ r = route_new(&route, RTPROT_STATIC);
if (r < 0)
return r;
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index ffc9578e86..f6cc1f8ee2 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -23,15 +23,16 @@
#include <linux/if.h>
#include <unistd.h>
-#include "util.h"
-#include "virt.h"
-#include "fileio.h"
-#include "socket-util.h"
#include "bus-util.h"
-#include "udev-util.h"
-#include "netlink-util.h"
#include "dhcp-lease-internal.h"
+#include "fileio.h"
+#include "netlink-util.h"
#include "network-internal.h"
+#include "set.h"
+#include "socket-util.h"
+#include "udev-util.h"
+#include "util.h"
+#include "virt.h"
#include "networkd-link.h"
#include "networkd-netdev.h"
@@ -291,10 +292,10 @@ static void link_free(Link *link) {
if (!link)
return;
- while ((address = link->addresses)) {
- LIST_REMOVE(addresses, link->addresses, address);
- address_free(address);
- }
+ while (!set_isempty(link->addresses))
+ address_free(set_first(link->addresses));
+
+ set_free(link->addresses);
while ((address = link->pool_addresses)) {
LIST_REMOVE(addresses, link->pool_addresses, address);
@@ -336,15 +337,28 @@ static void link_free(Link *link) {
}
Link *link_unref(Link *link) {
- if (link && (-- link->n_ref <= 0))
- link_free(link);
+ if (!link)
+ return NULL;
+
+ assert(link->n_ref > 0);
+
+ link->n_ref --;
+
+ if (link->n_ref > 0)
+ return NULL;
+
+ link_free(link);
return NULL;
}
Link *link_ref(Link *link) {
- if (link)
- assert_se(++ link->n_ref >= 2);
+ if (!link)
+ return NULL;
+
+ assert(link->n_ref > 0);
+
+ link->n_ref ++;
return link;
}
@@ -531,7 +545,7 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST)
- log_link_warning_errno(link, r, "%-*s: could not set route: %m", IFNAMSIZ, link->ifname);
+ log_link_warning_errno(link, r, "Could not set route: %m");
if (link->link_messages == 0) {
log_link_debug(link, "Routes set");
@@ -572,7 +586,7 @@ static int link_enter_set_routes(Link *link) {
return 0;
}
-int link_route_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
+int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_link_unref_ Link *link = userdata;
int r;
@@ -585,7 +599,7 @@ int link_route_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userd
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -ESRCH)
- log_link_warning_errno(link, r, "%-*s: could not drop route: %m", IFNAMSIZ, link->ifname);
+ log_link_warning_errno(link, r, "Could not drop route: %m");
return 1;
}
@@ -609,9 +623,9 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST)
- log_link_warning_errno(link, r, "%-*s: could not set address: %m", IFNAMSIZ, link->ifname);
+ log_link_warning_errno(link, r, "could not set address: %m");
else if (r >= 0)
- link_rtnl_process_address(rtnl, m, link->manager);
+ manager_rtnl_process_address(rtnl, m, link->manager);
if (link->link_messages == 0) {
log_link_debug(link, "Addresses set");
@@ -854,7 +868,7 @@ static int link_enter_set_addresses(Link *link) {
return 0;
}
-int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
+int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_link_unref_ Link *link = userdata;
int r;
@@ -867,7 +881,7 @@ int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *use
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EADDRNOTAVAIL)
- log_link_warning_errno(link, r, "%-*s: could not drop address: %m", IFNAMSIZ, link->ifname);
+ log_link_warning_errno(link, r, "Could not drop address: %m");
return 1;
}
@@ -1019,7 +1033,7 @@ static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
r = sd_netlink_message_get_errno(m);
if (r < 0)
- log_link_warning_errno(link, r, "%-*s: could not set MTU: %m", IFNAMSIZ, link->ifname);
+ log_link_warning_errno(link, r, "Could not set MTU: %m");
return 1;
}
@@ -1207,7 +1221,7 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
if (r < 0)
/* we warn but don't fail the link, as it may be
brought up later */
- log_link_warning_errno(link, r, "%-*s: could not bring up interface: %m", IFNAMSIZ, link->ifname);
+ log_link_warning_errno(link, r, "Could not bring up interface: %m");
return 1;
}
@@ -1294,7 +1308,7 @@ static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *user
r = sd_netlink_message_get_errno(m);
if (r < 0)
- log_link_warning_errno(link, r, "%-*s: could not bring down interface: %m", IFNAMSIZ, link->ifname);
+ log_link_warning_errno(link, r, "Could not bring down interface: %m");
return 1;
}
@@ -1616,7 +1630,7 @@ static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *us
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
- log_link_error_errno(link, r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname);
+ log_link_error_errno(link, r, "Could not join netdev: %m");
link_enter_failed(link);
return 1;
} else
@@ -1812,16 +1826,16 @@ static int link_set_ipv6_accept_ra(Link *link) {
* disabled if local forwarding is enabled).
* If set, ignore or enforce RA independent of local forwarding state.
*/
- if (link->network->ipv6_accept_ra < 0) {
+ if (link->network->ipv6_accept_ra < 0)
/* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
v = "1";
- } else if (link->network->ipv6_accept_ra > 0) {
+ else if (link->network->ipv6_accept_ra > 0)
/* "2" means accept RA even if ip_forward is enabled */
v = "2";
- } else {
+ else
/* "0" means ignore RA */
v = "0";
- }
+
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
r = write_string_file(p, v, 0);
@@ -2011,179 +2025,6 @@ int link_initialized(Link *link, struct udev_device *device) {
return 0;
}
-static Address* link_get_equal_address(Link *link, Address *needle) {
- Address *i;
-
- assert(link);
- assert(needle);
-
- LIST_FOREACH(addresses, i, link->addresses)
- if (address_equal(i, needle))
- return i;
-
- return NULL;
-}
-
-int link_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
- Manager *m = userdata;
- Link *link = NULL;
- uint16_t type;
- _cleanup_address_free_ Address *address = NULL;
- unsigned char flags;
- Address *existing;
- char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
- const char *valid_str = NULL;
- int r, ifindex;
-
- assert(rtnl);
- assert(message);
- assert(m);
-
- if (sd_netlink_message_is_error(message)) {
- r = sd_netlink_message_get_errno(message);
- if (r < 0)
- log_warning_errno(r, "rtnl: failed to receive address: %m");
-
- return 0;
- }
-
- r = sd_netlink_message_get_type(message, &type);
- if (r < 0) {
- log_warning_errno(r, "rtnl: could not get message type: %m");
- return 0;
- } else if (type != RTM_NEWADDR && type != RTM_DELADDR) {
- log_warning("rtnl: received unexpected message type when processing address");
- return 0;
- }
-
- r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
- if (r < 0) {
- log_warning_errno(r, "rtnl: could not get ifindex from address: %m");
- return 0;
- } else if (ifindex <= 0) {
- log_warning("rtnl: received address message with invalid ifindex: %d", ifindex);
- return 0;
- } else {
- r = link_get(m, ifindex, &link);
- if (r < 0 || !link) {
- /* when enumerating we might be out of sync, but we will
- * get the address again, so just ignore it */
- if (!m->enumerating)
- log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
- return 0;
- }
- }
-
- r = address_new_dynamic(&address);
- if (r < 0)
- return r;
-
- r = sd_rtnl_message_addr_get_family(message, &address->family);
- if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
- log_link_warning(link, "rtnl: received address with invalid family, ignoring.");
- return 0;
- }
-
- r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m");
- return 0;
- }
-
- r = sd_rtnl_message_addr_get_scope(message, &address->scope);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m");
- return 0;
- }
-
- r = sd_rtnl_message_addr_get_flags(message, &flags);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m");
- return 0;
- }
- address->flags = flags;
-
- switch (address->family) {
- case AF_INET:
- r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
- return 0;
- }
-
- break;
-
- case AF_INET6:
- r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
- if (r < 0) {
- log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
- return 0;
- }
-
- break;
-
- default:
- assert_not_reached("invalid address family");
- }
-
- if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
- log_link_warning(link, "Could not print address");
- return 0;
- }
-
- r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &address->cinfo);
- if (r >= 0) {
- if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
- valid_str = "ever";
- else
- valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
- address->cinfo.ifa_valid * USEC_PER_SEC,
- USEC_PER_SEC);
- }
-
- existing = link_get_equal_address(link, address);
-
- switch (type) {
- case RTM_NEWADDR:
- if (existing) {
- log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
-
-
- existing->scope = address->scope;
- existing->flags = address->flags;
- existing->cinfo = address->cinfo;
-
- } else {
- log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
-
- LIST_PREPEND(addresses, link->addresses, address);
- address_establish(address, link);
-
- address = NULL;
-
- link_save(link);
- }
-
- break;
-
- case RTM_DELADDR:
-
- if (existing) {
- log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
- address_release(existing, link);
- LIST_REMOVE(addresses, link->addresses, existing);
- address_free(existing);
- } else
- log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
-
- break;
- default:
- assert_not_reached("Received invalid RTNL message type");
- }
-
- return 1;
-}
-
int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
Link *link;
_cleanup_udev_device_unref_ struct udev_device *device = NULL;
@@ -2207,8 +2048,10 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
/* not in a container, udev will be around */
sprintf(ifindex_str, "n%d", link->ifindex);
device = udev_device_new_from_device_id(m->udev, ifindex_str);
- if (!device)
- return log_link_warning_errno(link, errno, "Could not find udev device: %m");
+ if (!device) {
+ r = log_link_warning_errno(link, errno, "Could not find udev device: %m");
+ goto failed;
+ }
if (udev_device_get_is_initialized(device) <= 0) {
/* not yet ready */
@@ -2218,17 +2061,20 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
r = link_initialized(link, device);
if (r < 0)
- return r;
+ goto failed;
} else {
/* we are calling a callback directly, so must take a ref */
link_ref(link);
r = link_initialized_and_synced(m->rtnl, NULL, link);
if (r < 0)
- return r;
+ goto failed;
}
return 0;
+failed:
+ link_enter_failed(link);
+ return r;
}
static int link_carrier_gained(Link *link) {
@@ -2425,10 +2271,11 @@ static void link_update_operstate(Link *link) {
else if (link_has_carrier(link)) {
Address *address;
uint8_t scope = RT_SCOPE_NOWHERE;
+ Iterator i;
/* if we have carrier, check what addresses we have */
- LIST_FOREACH(addresses, address, link->addresses) {
- if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
+ SET_FOREACH(address, link->addresses, i) {
+ if (!address_is_ready(address))
continue;
if (address->scope < scope)
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 7b219c6854..b81bae3830 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -83,7 +83,7 @@ struct Link {
unsigned link_messages;
unsigned enslaving;
- LIST_HEAD(Address, addresses);
+ Set *addresses;
sd_dhcp_client *dhcp_client;
sd_dhcp_lease *dhcp_lease;
@@ -120,8 +120,8 @@ int link_get(Manager *m, int ifindex, Link **ret);
int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
void link_drop(Link *link);
-int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
-int link_route_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
+int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
+int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
void link_enter_failed(Link *link);
int link_initialized(Link *link, struct udev_device *device);
@@ -129,7 +129,6 @@ int link_initialized(Link *link, struct udev_device *device);
void link_client_handler(Link *link);
int link_update(Link *link, sd_netlink_message *message);
-int link_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata);
int link_save(Link *link);
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index b4259cafef..07e47b668c 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -277,6 +277,166 @@ static int manager_connect_udev(Manager *m) {
return 0;
}
+int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
+ Manager *m = userdata;
+ Link *link = NULL;
+ uint16_t type;
+ unsigned char flags;
+ int family;
+ unsigned char prefixlen;
+ unsigned char scope;
+ union in_addr_union in_addr;
+ struct ifa_cacheinfo cinfo;
+ Address *address = NULL;
+ char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
+ const char *valid_str = NULL;
+ int r, ifindex;
+
+ assert(rtnl);
+ assert(message);
+ assert(m);
+
+ if (sd_netlink_message_is_error(message)) {
+ r = sd_netlink_message_get_errno(message);
+ if (r < 0)
+ log_warning_errno(r, "rtnl: failed to receive address: %m");
+
+ return 0;
+ }
+
+ r = sd_netlink_message_get_type(message, &type);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get message type: %m");
+ return 0;
+ } else if (type != RTM_NEWADDR && type != RTM_DELADDR) {
+ log_warning("rtnl: received unexpected message type when processing address");
+ return 0;
+ }
+
+ r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get ifindex from address: %m");
+ return 0;
+ } else if (ifindex <= 0) {
+ log_warning("rtnl: received address message with invalid ifindex: %d", ifindex);
+ return 0;
+ } else {
+ r = link_get(m, ifindex, &link);
+ if (r < 0 || !link) {
+ /* when enumerating we might be out of sync, but we will
+ * get the address again, so just ignore it */
+ if (!m->enumerating)
+ log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
+ return 0;
+ }
+ }
+
+ r = sd_rtnl_message_addr_get_family(message, &family);
+ if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) {
+ log_link_warning(link, "rtnl: received address with invalid family, ignoring.");
+ return 0;
+ }
+
+ r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_rtnl_message_addr_get_scope(message, &scope);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_rtnl_message_addr_get_flags(message, &flags);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m");
+ return 0;
+ }
+
+ switch (family) {
+ case AF_INET:
+ r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &in_addr.in);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
+ return 0;
+ }
+
+ break;
+
+ case AF_INET6:
+ r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &in_addr.in6);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
+ return 0;
+ }
+
+ break;
+
+ default:
+ assert_not_reached("invalid address family");
+ }
+
+ if (!inet_ntop(family, &in_addr, buf, INET6_ADDRSTRLEN)) {
+ log_link_warning(link, "Could not print address");
+ return 0;
+ }
+
+ r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo);
+ if (r >= 0) {
+ if (cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
+ valid_str = "ever";
+ else
+ valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
+ cinfo.ifa_valid * USEC_PER_SEC,
+ USEC_PER_SEC);
+ }
+
+ address_get(link, family, &in_addr, prefixlen, &address);
+
+ switch (type) {
+ case RTM_NEWADDR:
+ if (address) {
+ log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
+
+ address->scope = scope;
+ address->flags = flags;
+ address->cinfo = cinfo;
+
+ } else {
+ r = address_add(link, family, &in_addr, prefixlen, &address);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to add address %s/%u: %m", buf, prefixlen);
+ return 0;
+ } else
+ log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
+
+ address->scope = scope;
+ address->flags = flags;
+ address->cinfo = cinfo;
+
+ link_save(link);
+ }
+
+ break;
+
+ case RTM_DELADDR:
+
+ if (address) {
+ log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
+ address_drop(address);
+ } else
+ log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
+
+ break;
+ default:
+ assert_not_reached("Received invalid RTNL message type");
+ }
+
+ return 1;
+}
+
static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
Manager *m = userdata;
Link *link = NULL;
@@ -410,11 +570,11 @@ static int manager_connect_rtnl(Manager *m) {
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
+ r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, &manager_rtnl_process_address, m);
if (r < 0)
return r;
- r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
+ r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, &manager_rtnl_process_address, m);
if (r < 0)
return r;
@@ -477,14 +637,6 @@ void manager_free(Manager *m) {
free(m->state_file);
- sd_event_source_unref(m->udev_event_source);
- udev_monitor_unref(m->udev_monitor);
- udev_unref(m->udev);
-
- sd_bus_unref(m->bus);
- sd_bus_slot_unref(m->prepare_for_sleep_slot);
- sd_event_source_unref(m->bus_retry_event_source);
-
while ((link = hashmap_first(m->links)))
link_unref(link);
hashmap_free(m->links);
@@ -504,6 +656,14 @@ void manager_free(Manager *m) {
sd_netlink_unref(m->rtnl);
sd_event_unref(m->event);
+ sd_event_source_unref(m->udev_event_source);
+ udev_monitor_unref(m->udev_monitor);
+ udev_unref(m->udev);
+
+ sd_bus_unref(m->bus);
+ sd_bus_slot_unref(m->prepare_for_sleep_slot);
+ sd_event_source_unref(m->bus_retry_event_source);
+
free(m);
}
@@ -633,7 +793,7 @@ int manager_rtnl_enumerate_addresses(Manager *m) {
m->enumerating = true;
- k = link_rtnl_process_address(m->rtnl, addr, m);
+ k = manager_rtnl_process_address(m->rtnl, addr, m);
if (k < 0)
r = k;
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 5d22598fc0..bdee7f1923 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -326,12 +326,12 @@ int network_get(Manager *manager, struct udev_device *device,
(void) safe_atou8(attr, &name_assign_type);
if (name_assign_type == NET_NAME_ENUM)
- log_warning("%-*s: found matching network '%s', based on potentially unpredictable ifname",
- IFNAMSIZ, ifname, network->filename);
+ log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
+ ifname, network->filename);
else
- log_debug("%-*s: found matching network '%s'", IFNAMSIZ, ifname, network->filename);
+ log_debug("%s: found matching network '%s'", ifname, network->filename);
} else
- log_debug("%-*s: found matching network '%s'", IFNAMSIZ, ifname, network->filename);
+ log_debug("%s: found matching network '%s'", ifname, network->filename);
*ret = network;
return 0;
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index ee1ddd81fe..1c8302ffaa 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -26,8 +26,26 @@
#include "networkd.h"
#include "networkd-route.h"
+int route_new(Route **ret, unsigned char rtm_protocol) {
+ _cleanup_route_free_ Route *route = NULL;
+
+ route = new0(Route, 1);
+ if (!route)
+ return -ENOMEM;
+
+ route->family = AF_UNSPEC;
+ route->scope = RT_SCOPE_UNIVERSE;
+ route->protocol = rtm_protocol;
+
+ *ret = route;
+ route = NULL;
+
+ return 0;
+}
+
int route_new_static(Network *network, unsigned section, Route **ret) {
_cleanup_route_free_ Route *route = NULL;
+ int r;
if (section) {
route = hashmap_get(network->routes_by_section,
@@ -40,13 +58,9 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
}
}
- route = new0(Route, 1);
- if (!route)
- return -ENOMEM;
-
- route->family = AF_UNSPEC;
- route->scope = RT_SCOPE_UNIVERSE;
- route->protocol = RTPROT_STATIC;
+ r = route_new(&route, RTPROT_STATIC);
+ if (r < 0)
+ return r;
route->network = network;
@@ -64,23 +78,6 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
return 0;
}
-int route_new_dynamic(Route **ret, unsigned char rtm_protocol) {
- _cleanup_route_free_ Route *route = NULL;
-
- route = new0(Route, 1);
- if (!route)
- return -ENOMEM;
-
- route->family = AF_UNSPEC;
- route->scope = RT_SCOPE_UNIVERSE;
- route->protocol = rtm_protocol;
-
- *ret = route;
- route = NULL;
-
- return 0;
-}
-
void route_free(Route *route) {
if (!route)
return;
@@ -96,7 +93,7 @@ void route_free(Route *route) {
free(route);
}
-int route_drop(Route *route, Link *link,
+int route_remove(Route *route, Link *link,
sd_netlink_message_handler_t callback) {
_cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
int r;
diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h
index 11e94d44fb..e3ed1be866 100644
--- a/src/network/networkd-route.h
+++ b/src/network/networkd-route.h
@@ -46,10 +46,10 @@ struct Route {
};
int route_new_static(Network *network, unsigned section, Route **ret);
-int route_new_dynamic(Route **ret, unsigned char rtm_protocol);
+int route_new(Route **ret, unsigned char rtm_protocol);
void route_free(Route *route);
int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback);
-int route_drop(Route *route, Link *link, sd_netlink_message_handler_t callback);
+int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback);
DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free);
#define _cleanup_route_free_ _cleanup_(route_freep)
diff --git a/src/network/networkd.h b/src/network/networkd.h
index eea57ac158..cbec6d5b7e 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -80,6 +80,8 @@ bool manager_should_reload(Manager *m);
int manager_rtnl_enumerate_links(Manager *m);
int manager_rtnl_enumerate_addresses(Manager *m);
+int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, void *userdata);
+
int manager_send_changed(Manager *m, const char *property, ...) _sentinel_;
int manager_save(Manager *m);
diff --git a/src/network/test-network.c b/src/network/test-network.c
index 5909cc790e..bac1d6781d 100644
--- a/src/network/test-network.c
+++ b/src/network/test-network.c
@@ -143,8 +143,8 @@ static void test_network_get(Manager *manager, struct udev_device *loopback) {
static void test_address_equality(void) {
_cleanup_address_free_ Address *a1 = NULL, *a2 = NULL;
- assert_se(address_new_dynamic(&a1) >= 0);
- assert_se(address_new_dynamic(&a2) >= 0);
+ assert_se(address_new(&a1) >= 0);
+ assert_se(address_new(&a2) >= 0);
assert_se(address_equal(NULL, NULL));
assert_se(!address_equal(a1, NULL));
@@ -158,17 +158,18 @@ static void test_address_equality(void) {
assert_se(address_equal(a1, a2));
assert_se(inet_pton(AF_INET, "192.168.3.9", &a1->in_addr.in));
- assert_se(address_equal(a1, a2));
+ assert_se(!address_equal(a1, a2));
assert_se(inet_pton(AF_INET, "192.168.3.9", &a2->in_addr.in));
assert_se(address_equal(a1, a2));
+ assert_se(inet_pton(AF_INET, "192.168.3.10", &a1->in_addr_peer.in));
+ assert_se(address_equal(a1, a2));
+ assert_se(inet_pton(AF_INET, "192.168.3.11", &a2->in_addr_peer.in));
+ assert_se(address_equal(a1, a2));
a1->prefixlen = 10;
assert_se(!address_equal(a1, a2));
a2->prefixlen = 10;
assert_se(address_equal(a1, a2));
- assert_se(inet_pton(AF_INET, "192.168.3.10", &a2->in_addr.in));
- assert_se(address_equal(a1, a2));
-
a1->family = AF_INET6;
assert_se(!address_equal(a1, a2));
diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c
index 3d302ef9ad..6c8b1d7a26 100644
--- a/src/nspawn/nspawn-mount.c
+++ b/src/nspawn/nspawn-mount.c
@@ -710,13 +710,15 @@ static int mount_unified_cgroups(const char *dest) {
assert(dest);
- p = strjoina(dest, "/sys/fs/cgroup");
+ p = prefix_roota(dest, "/sys/fs/cgroup");
+
+ (void) mkdir_p(p, 0755);
r = path_is_mount_point(p, AT_SYMLINK_FOLLOW);
if (r < 0)
return log_error_errno(r, "Failed to determine if %s is mounted already: %m", p);
if (r > 0) {
- p = strjoina(dest, "/sys/fs/cgroup/cgroup.procs");
+ p = prefix_roota(dest, "/sys/fs/cgroup/cgroup.procs");
if (access(p, F_OK) >= 0)
return 0;
if (errno != ENOENT)
diff --git a/src/rfkill/rfkill.c b/src/rfkill/rfkill.c
index d8a2f3694e..72c9eb4446 100644
--- a/src/rfkill/rfkill.c
+++ b/src/rfkill/rfkill.c
@@ -40,8 +40,8 @@ static const char* const rfkill_type_table[NUM_RFKILL_TYPES] = {
[RFKILL_TYPE_WIMAX] = "wimax",
[RFKILL_TYPE_WWAN] = "wwan",
[RFKILL_TYPE_GPS] = "gps",
- [RFKILL_TYPE_FM] "fm",
- [RFKILL_TYPE_NFC] "nfc",
+ [RFKILL_TYPE_FM] = "fm",
+ [RFKILL_TYPE_NFC] = "nfc",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(rfkill_type, int);
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index 10df3fc3d6..a5d6edbba9 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -1426,7 +1426,8 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
"CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
"SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
- "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges")) {
+ "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
+ "SyslogLevelPrefix")) {
r = parse_boolean(eq);
if (r < 0) {
@@ -1493,10 +1494,32 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
"UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath",
"StandardInput", "StandardOutput", "StandardError",
"Description", "Slice", "Type", "WorkingDirectory",
- "RootDirectory"))
+ "RootDirectory", "SyslogIdentifier"))
r = sd_bus_message_append(m, "v", "s", eq);
- else if (streq(field, "DeviceAllow")) {
+ else if (streq(field, "SyslogLevel")) {
+ int level;
+
+ level = log_level_from_string(eq);
+ if (level < 0) {
+ log_error("Failed to parse %s value %s.", field, eq);
+ return -EINVAL;
+ }
+
+ r = sd_bus_message_append(m, "v", "i", level);
+
+ } else if (streq(field, "SyslogFacility")) {
+ int facility;
+
+ facility = log_facility_unshifted_from_string(eq);
+ if (facility < 0) {
+ log_error("Failed to parse %s value %s.", field, eq);
+ return -EINVAL;
+ }
+
+ r = sd_bus_message_append(m, "v", "i", facility);
+
+ } else if (streq(field, "DeviceAllow")) {
if (isempty(eq))
r = sd_bus_message_append(m, "v", "a(ss)", 0);
@@ -1632,7 +1655,16 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
}
r = sd_bus_message_append(m, "v", "t", u);
+ } else if (streq(field, "TimerSlackNSec")) {
+ nsec_t n;
+ r = parse_nsec(eq, &n);
+ if (r < 0) {
+ log_error("Failed to parse %s value %s", field, eq);
+ return -EINVAL;
+ }
+
+ r = sd_bus_message_append(m, "v", "t", n);
} else {
log_error("Unknown assignment %s.", assignment);
return -EINVAL;
@@ -2137,3 +2169,42 @@ bool is_kdbus_available(void) {
return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;
}
+
+int bus_property_get_rlimit(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ struct rlimit *rl;
+ uint64_t u;
+ rlim_t x;
+
+ assert(bus);
+ assert(reply);
+ assert(userdata);
+
+ rl = *(struct rlimit**) userdata;
+ if (rl)
+ x = rl->rlim_max;
+ else {
+ struct rlimit buf = {};
+ int z;
+
+ z = rlimit_from_string(strstr(property, "Limit"));
+ assert(z >= 0);
+
+ getrlimit(z, &buf);
+ x = buf.rlim_max;
+ }
+
+ /* rlim_t might have different sizes, let's map
+ * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
+ * all archs */
+ u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
+
+ return sd_bus_message_append(reply, "t", u);
+}
diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h
index f03f951dc7..fd70842b9e 100644
--- a/src/shared/bus-util.h
+++ b/src/shared/bus-util.h
@@ -200,3 +200,5 @@ int bus_path_decode_unique(const char *path, const char *prefix, char **ret_send
bool is_kdbus_wanted(void);
bool is_kdbus_available(void);
+
+int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c
index db2146f8c1..c065adcfdf 100644
--- a/src/shared/fstab-util.c
+++ b/src/shared/fstab-util.c
@@ -25,7 +25,6 @@
#include "util.h"
bool fstab_is_mount_point(const char *mount) {
- _cleanup_free_ char *device = NULL;
_cleanup_endmntent_ FILE *f = NULL;
struct mntent *m;
diff --git a/src/systemd/sd-ipv4ll.h b/src/systemd/sd-ipv4ll.h
index 677505f0c6..cc85140acd 100644
--- a/src/systemd/sd-ipv4ll.h
+++ b/src/systemd/sd-ipv4ll.h
@@ -43,6 +43,7 @@ int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address);
int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata);
int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr);
int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index);
+int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address);
int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, unsigned seed);
bool sd_ipv4ll_is_running(sd_ipv4ll *ll);
int sd_ipv4ll_start(sd_ipv4ll *ll);
diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h
index e09b8c8e2d..8e1b06ee9a 100644
--- a/src/systemd/sd-netlink.h
+++ b/src/systemd/sd-netlink.h
@@ -137,6 +137,10 @@ int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char
int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope);
int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family);
+int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol);
+int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope);
+int sd_rtnl_message_route_get_tos(sd_netlink_message *m, unsigned char *tos);
+int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table);
int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len);
int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len);
diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
index 87e1da1258..ad36ef19b0 100644
--- a/src/test/test-calendarspec.c
+++ b/src/test/test-calendarspec.c
@@ -50,6 +50,44 @@ static void test_one(const char *input, const char *output) {
assert_se(streq(q, p));
}
+static void test_next(const char *input, const char *new_tz, usec_t after, usec_t expect) {
+ CalendarSpec *c;
+ usec_t u;
+ char *old_tz;
+ char buf[FORMAT_TIMESTAMP_MAX];
+ int r;
+
+ old_tz = getenv("TZ");
+ if (old_tz)
+ old_tz = strdupa(old_tz);
+
+ if (new_tz)
+ assert_se(setenv("TZ", new_tz, 1) >= 0);
+ else
+ assert_se(unsetenv("TZ") >= 0);
+ tzset();
+
+ assert_se(calendar_spec_from_string(input, &c) >= 0);
+
+ printf("\"%s\"\n", input);
+
+ u = after;
+ r = calendar_spec_next_usec(c, after, &u);
+ printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp(buf, sizeof(buf), u));
+ if (expect != (usec_t)-1)
+ assert_se(r >= 0 && u == expect);
+ else
+ assert(r == -ENOENT);
+
+ calendar_spec_free(c);
+
+ if (old_tz)
+ assert_se(setenv("TZ", old_tz, 1) >= 0);
+ else
+ assert_se(unsetenv("TZ") >= 0);
+ tzset();
+}
+
int main(int argc, char* argv[]) {
CalendarSpec *c;
@@ -82,6 +120,15 @@ int main(int argc, char* argv[]) {
test_one("semi-annually", "*-01,07-01 00:00:00");
test_one("annually", "*-01-01 00:00:00");
test_one("*:2/3", "*-*-* *:02/3:00");
+ test_one("2015-10-25 01:00:00 uTc", "2015-10-25 01:00:00 UTC");
+
+ test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000);
+ test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000);
+ test_next("2016-03-27 03:17:00", "EET", 12345, -1);
+ test_next("2016-03-27 03:17:00 UTC", NULL, 12345, 1459048620000000);
+ test_next("2016-03-27 03:17:00 UTC", "", 12345, 1459048620000000);
+ test_next("2016-03-27 03:17:00 UTC", "CET", 12345, 1459048620000000);
+ test_next("2016-03-27 03:17:00 UTC", "EET", 12345, 1459048620000000);
assert_se(calendar_spec_from_string("test", &c) < 0);
assert_se(calendar_spec_from_string("", &c) < 0);
diff --git a/src/test/test-date.c b/src/test/test-date.c
index 00b569080c..bd1b2781df 100644
--- a/src/test/test-date.c
+++ b/src/test/test-date.c
@@ -23,12 +23,12 @@
#include "util.h"
-static void test_one(const char *p) {
+static void test_should_pass(const char *p) {
usec_t t, q;
char buf[FORMAT_TIMESTAMP_MAX], buf_relative[FORMAT_TIMESTAMP_RELATIVE_MAX];
assert_se(parse_timestamp(p, &t) >= 0);
- format_timestamp(buf, sizeof(buf), t);
+ format_timestamp_us(buf, sizeof(buf), t);
log_info("%s", buf);
/* Chop off timezone */
@@ -42,23 +42,50 @@ static void test_one(const char *p) {
assert_se(parse_timestamp(buf, &q) >= 0);
}
+static void test_should_fail(const char *p) {
+ usec_t t;
+
+ assert_se(parse_timestamp(p, &t) < 0);
+}
+
+static void test_one(const char *p) {
+ _cleanup_free_ char *with_utc;
+
+ log_info("Test: %s", p);
+ with_utc = strjoin(p, " UTC", NULL);
+ test_should_pass(p);
+ test_should_pass(with_utc);
+}
+
+static void test_one_noutc(const char *p) {
+ _cleanup_free_ char *with_utc;
+
+ log_info("Test: %s", p);
+ with_utc = strjoin(p, " UTC", NULL);
+ test_should_pass(p);
+ test_should_fail(with_utc);
+}
+
int main(int argc, char *argv[]) {
test_one("17:41");
test_one("18:42:44");
+ test_one("18:42:44.0");
+ test_one("18:42:44.999999999999");
test_one("12-10-02 12:13:14");
test_one("12-10-2 12:13:14");
test_one("12-10-03 12:13");
test_one("2012-12-30 18:42");
test_one("2012-10-02");
test_one("Tue 2012-10-02");
- test_one("now");
+ test_one_noutc("now");
test_one("yesterday");
test_one("today");
test_one("tomorrow");
- test_one("+2d");
- test_one("+2y 4d");
- test_one("5months ago");
- test_one("@1395716396");
+ test_one_noutc("+2d");
+ test_one_noutc("+2y 4d");
+ test_one_noutc("5months ago");
+ test_one_noutc("@1395716396");
+ test_one_noutc("today UTC");
return 0;
}
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
index 93cce186f0..53986babae 100644
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -381,7 +381,7 @@ static int wall_tty_block(void) {
fd = open(p, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
if (fd < 0)
- return log_error_errno(errno, "Failed to open %s: %m", p);
+ return log_debug_errno(errno, "Failed to open %s: %m", p);
return fd;
}
diff --git a/src/udev/.gitignore b/src/udev/.gitignore
index ba112ce218..f5d8be3dc1 100644
--- a/src/udev/.gitignore
+++ b/src/udev/.gitignore
@@ -1,5 +1,4 @@
/udev.pc
/keyboard-keys-from-name.gperf
/keyboard-keys-from-name.h
-/keyboard-keys-to-name.h
/keyboard-keys-list.txt
diff --git a/systemd-master/catalog/systemd.da.catalog b/systemd-master/catalog/systemd.da.catalog
new file mode 100644
index 0000000000..dc3f8b552e
--- /dev/null
+++ b/systemd-master/catalog/systemd.da.catalog
@@ -0,0 +1,261 @@
+# This file is part of systemd.
+#
+# Copyright 2012 Lennart Poettering
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+
+# Message catalog for systemd's own messages
+# Danish translation
+
+# The catalog format is documented on
+# http://www.freedesktop.org/wiki/Software/systemd/catalog
+
+# For an explanation why we do all this, see https://xkcd.com/1024/
+
+-- f77379a8490b408bbe5f6940505a777b
+Subject: Journalen er blevet startet
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+System-journal processen har startet op, åbnet journal filerne for
+tilskrivning og er nu klar til at modtage anmodninger.
+
+-- d93fb3c9c24d451a97cea615ce59c00b
+Subject: Journalen er blevet stoppet
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+System-journal processen er stoppet og har lukket alle aktive journal
+filer.
+
+-- a596d6fe7bfa4994828e72309e95d61e
+Subject: Beskeder fra en service er blevet undertrykt
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: man:journald.conf(5)
+
+En service har logget for mange beskeder inden for en given tidsperiode.
+Beskeder fra omtalte service er blevet smidt væk.
+
+Kun beskeder fra omtalte service er smidt væk. Beskeder fra andre
+services er ikke påvirket.
+
+Grænsen for hvornår beskeder bliver smidt væk kan konfigureres
+med RateLimitInterval= og RateLimitBurst= i
+/etc/systemd/journald.conf. Se journald.conf(5) for detaljer herom.
+
+-- e9bf28e6e834481bb6f48f548ad13606
+Subject: Journal beskeder er gået tabt
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Kernel beskeder er gået tabt da journal systemet ikke har været i stand
+til at håndtere dem hurtigt nok.
+
+-- fc2e22bc6ee647b6b90729ab34a250b1
+Subject: Fejl-fil genereret for process @COREDUMP_PID@ (@COREDUMP_COMM@)
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: man:core(5)
+
+Process @COREDUMP_PID@ (@COREDUMP_COMM@) har lukket ned og genereret en
+fejl-fil.
+
+Dette indikerer som regel en programmeringsfejl i det nedlukkede program
+og burde blive reporteret som en bug til folkene bag
+
+-- 8d45620c1a4348dbb17410da57c60c66
+Subject: En ny session @SESSION_ID@ er blevet lavet for bruger @USER_ID@
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat
+
+En ny session med ID @SESSION_ID@ er blevet lavet for brugeren @USER_ID@.
+
+Den ledende process for sessionen er @LEADER@.
+
+-- 3354939424b4456d9802ca8333ed424a
+Subject: Session @SESSION_ID@ er blevet lukket ned
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat
+
+En session med ID @SESSION_ID@ er blevet lukket ned.
+
+-- fcbefc5da23d428093f97c82a9290f7b
+Subject: En ny arbejdsstation $SEAT_ID@ er nu tilgængelig
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat
+
+En ny arbejdsstation @SEAT_ID@ er blevet konfigureret og er nu tilgængelig.
+
+-- e7852bfe46784ed0accde04bc864c2d5
+Subject: Arbejdsstation @SEAT_ID@ er nu blevet fjernet
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat
+
+En arbejdsstation @SEAT_ID@ er blevet fjernet og er ikke længere tilgængelig.
+
+-- c7a787079b354eaaa9e77b371893cd27
+Subject: Tidsændring
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Systemtiden er blevet ændret til @REALTIME@ mikrosekunder efter d. 1. Januar 1970.
+
+-- 45f82f4aef7a4bbf942ce861d1f20990
+Subject: Tidszoneændring til @TIMEZONE@
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Tidszonen for systemet er blevet ændret til @TIMEZONE@.
+
+-- b07a249cd024414a82dd00cd181378ff
+Subject: Opstart af systemet er nu fuldført
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Alle system services i kø til at køre ved opstart, er blevet startet
+med success. Bemærk at dette ikke betyder at maskinen er i dvale, da
+services stadig kan være i gang med at færdiggøre deres opstart.
+
+Opstart af kernel tog @KERNEL_USEC@ mikrosekunder.
+
+Opstart af initrd tog @INITRD_USEC@ mikrosekunder.
+
+Opstart af userspace tog @USERSPACE_USEC@ mikrosekunder.
+
+-- 6bbd95ee977941e497c48be27c254128
+Subject: System slumretilstand @SLEEP@ trådt i kraft
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+System er nu gået i @SLEEP@ slumretilstand.
+
+-- 8811e6df2a8e40f58a94cea26f8ebf14
+Subject: System slumretilstand @SLEEP@ forladt
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Systemet har nu forladt @SLEEP@ slumretilstand.
+
+-- 98268866d1d54a499c4e98921d93bc40
+Subject: Systemnedlukning påbegyndt
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Systemnedlukning er blevet påbegyndt. Nedlukningen er nu begyndt og
+alle system services er blevet afbrudt og alle filsystemer afmonteret.
+
+-- 7d4958e842da4a758f6c1cdc7b36dcc5
+Subject: Enhed @UNIT@ har påbegyndt opstart
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Enhed @UNIT@ er begyndt at starte op.
+
+-- 39f53479d3a045ac8e11786248231fbf
+Subject: Enhed @UNIT har færdiggjort opstart
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Enhed @UNIT@ er færdig med at starte op.
+
+Resultat for opstart er @RESULT@.
+
+-- de5b426a63be47a7b6ac3eaac82e2f6f
+Subject: Enhed @UNIT@ har påbegyndt nedlukning
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Enhed @UNIT@ har påbegyndt nedlukning.
+
+-- 9d1aaa27d60140bd96365438aad20286
+Subject: Enhed @UNIT@ har færdiggjort nedlukning
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Enhed @UNIT@ har færdiggjort nedlukning.
+
+-- be02cf6855d2428ba40df7e9d022f03d
+Subject: Enhed @UNIT@ har fejlet
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Enhed @UNIT@ har fejlet.
+
+Resultatet er @RESULT@
+
+-- d34d037fff1847e6ae669a370e694725
+Subject: Enhed @UNIT@ har påbegyndt genindlæsning af sin konfiguration
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Enhed @UNIT@ er begyndt at genindlæse sin konfiguration
+
+-- 7b05ebc668384222baa8881179cfda54
+Subject: Enhed @UNIT@ har færdiggjort genindlæsning af sin konfiguration
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Enhed @UNIT@ er færdig med at genindlæse sin konfiguration
+
+Resultatet er: @RESULT@.
+
+-- 641257651c1b4ec9a8624d7a40a9e1e7
+Subject: Process @EXECUTABLE@ kunne ikke eksekveres
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Processen @EXECUTABLE@ kunne ikke eksekveres og fejlede.
+
+Processens returnerede fejlkode er @ERRNO@.
+
+-- 0027229ca0644181a76c4e92458afa2e
+Subject: Èn eller flere beskeder kunne ikke videresendes til syslog
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Èn eller flere beskeder kunne ikke videresendes til syslog servicen
+der kører side-om-side med journald. Dette indikerer typisk at syslog
+implementationen ikke har kunnet følge med mængden af ventende beskeder.
+
+-- 1dee0369c7fc4736b7099b38ecb46ee7
+Subject: Monteringspunkt er ikke tomt
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Folderen @WHERE@ er specificeret som monteringspunkt (andet felt i
+/etc/fstab eller Where= feltet i systemd enhedsfil) men er ikke tom.
+Dette forstyrrer ikke monteringen, men de pre-eksisterende filer i folderen
+bliver utilgængelige. For at se de over-monterede filer; montér det
+underlæggende filsystem til en anden lokation.
+
+-- 24d8d4452573402496068381a6312df2
+Subject: En virtuel maskine eller container er blevet startet
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Den virtuelle maskine @NAME@ med dens leder PID @LEADER@ er blevet
+startet og er klar til brug.
+
+-- 58432bd3bace477cb514b56381b8a758
+Subject: En virtuel maskine eller container er blevet afbrudt
+Defined-By: systemd
+Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
+
+Den virtuelle maskine @NAME@ med dens leder PID @LEADER@ er blevet
+nedlukket.
diff --git a/units/.gitignore b/units/.gitignore
index 883f51f73c..c89740df05 100644
--- a/units/.gitignore
+++ b/units/.gitignore
@@ -78,4 +78,5 @@
/systemd-update-utmp.service
/systemd-user-sessions.service
/systemd-vconsole-setup.service
+/tmp.mount
/user@.service
diff --git a/units/tmp.mount b/units/tmp.mount.m4
index 00a0d28722..d537746dbf 100644
--- a/units/tmp.mount
+++ b/units/tmp.mount.m4
@@ -18,4 +18,6 @@ Before=local-fs.target umount.target
What=tmpfs
Where=/tmp
Type=tmpfs
-Options=mode=1777,strictatime
+m4_ifdef(`HAVE_SMACK',
+`Options=mode=1777,strictatime,smackfsroot=*',
+`Options=mode=1777,strictatime')
diff --git a/units/user/exit.target b/units/user/exit.target
index b0ad24c488..e8148b78c7 100644
--- a/units/user/exit.target
+++ b/units/user/exit.target
@@ -12,6 +12,3 @@ DefaultDependencies=no
Requires=systemd-exit.service
After=systemd-exit.service
AllowIsolate=yes
-
-[Install]
-Alias=ctrl-alt-del.target