rfkill: ['systemd-rfkill']
rpm: ['rpm scriptlets']
run: ['systemd-run']
- sd-boot: ['bootctl', 'systemd-boot', 'systemd-stub']
+ sd-boot/sd-stub/bootctl: ['bootctl', 'systemd-boot', 'systemd-stub']
sysctl: ['systemd-sysctl']
sysext: ['systemd-sysext']
systemctl: ['systemctl']
runs-on: ubuntu-22.04
if: github.repository == 'systemd/systemd'
env:
- COVERITY_SCAN_BRANCH_PATTERN: "${{ github.ref}}"
- COVERITY_SCAN_NOTIFICATION_EMAIL: ""
- COVERITY_SCAN_PROJECT_NAME: "${{ github.repository }}"
- # Set in repo settings -> secrets -> repository secrets
+ # Set in repo settings -> secrets -> actions
COVERITY_SCAN_TOKEN: "${{ secrets.COVERITY_SCAN_TOKEN }}"
- CURRENT_REF: "${{ github.ref }}"
+ COVERITY_SCAN_NOTIFICATION_EMAIL: "${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }}"
steps:
- name: Repository checkout
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- # https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
- - name: Set the $COVERITY_SCAN_NOTIFICATION_EMAIL env variable
- run: echo "COVERITY_SCAN_NOTIFICATION_EMAIL=$(git log -1 ${{ github.sha }} --pretty=\"%aE\")" >> "$GITHUB_ENV"
- - name: Install Coverity tools
- run: tools/get-coverity.sh
# Reuse the setup phase of the unit test script to avoid code duplication
- name: Install build dependencies
run: sudo -E .github/workflows/unit_tests.sh SETUP
- # Preconfigure with meson to prevent Coverity from capturing meson metadata
- - name: Preconfigure the build directory
- run: meson cov-build -Dman=false
- - name: Build
- run: tools/coverity.sh build
- - name: Upload the results
- run: tools/coverity.sh upload
+ - name: Build & upload the results
+ run: tools/coverity.sh
# missing shebangs)
# - .*\.(in|SKELETON) - all template/skeleton files
# except kernel-install
- # - tools/coverity\.sh - external file (with some modifications)
- FILTER_REGEX_EXCLUDE: .*/(man/.*|([^k]|k(k|ek)*([^ek]|e[^kr]))*(k(k|ek)*e?)?\.(in|SKELETON)|tools/coverity\.sh)$
+ FILTER_REGEX_EXCLUDE: .*/(man/.*|([^k]|k(k|ek)*([^ek]|e[^kr]))*(k(k|ek)*e?)?\.(in|SKELETON))$
VALIDATE_ALL_CODEBASE: false
VALIDATE_BASH: true
VALIDATE_GITHUB_ACTIONS: true
/mkosi.default.d/**/*local*.conf
/tags
.dir-locals-2.el
+.vscode/
UBUNTU_RELEASE="$(lsb_release -cs)"
create_container() {
- # Create autopkgtest LXC image; this sometimes fails with "Unable to fetch
- # GPG key from keyserver", so retry a few times with different keyservers.
- for keyserver in "keys.openpgp.org" "" "keyserver.ubuntu.com" "keys.gnupg.net"; do
- for retry in {1..5}; do
- sudo lxc-create -n "$CONTAINER" -t download -- -d "$DISTRO" -r "$RELEASE" -a "$ARCH" ${keyserver:+--keyserver "$keyserver"} && break 2
- sleep $((retry*retry))
- done
- done
+ sudo lxc-create -n "$CONTAINER" -t download -- -d "$DISTRO" -r "$RELEASE" -a "$ARCH"
# unconfine the container, otherwise some tests fail
echo 'lxc.apparmor.profile = unconfined' | sudo tee -a "/var/lib/lxc/$CONTAINER/config"
# now build the package and run the tests
rm -rf "$ARTIFACTS_DIR"
# autopkgtest exits with 2 for "some tests skipped", accept that
- "$AUTOPKGTEST_DIR/runner/autopkgtest" --env DEB_BUILD_OPTIONS=noudeb \
- --env TEST_UPSTREAM=1 ../systemd_*.dsc \
- -o "$ARTIFACTS_DIR" \
- -- lxc -s "$CONTAINER" \
+ sudo "$AUTOPKGTEST_DIR/runner/autopkgtest" --env DEB_BUILD_OPTIONS=noudeb \
+ --env TEST_UPSTREAM=1 ../systemd_*.dsc \
+ -o "$ARTIFACTS_DIR" \
+ -- lxc -s "$CONTAINER" \
|| [ $? -eq 2 ]
;;
*)
systemd System and Service Manager
-CHANGES WITH 252:
+CHANGES WITH 252 in spe:
Announcement of Future Feature Removal
sooner rather than later, if you haven't done so yet. Most of Linux
userspace has been ported over already.
+ New features:
+
+ * systemd-measure is a new helper to precalculate PCR measurements
+ to make it easier to set TPM2 policies.
+
+ Changes in systemd itself, i.e. the manager, and units
+
+ * The cpu controller is delegated to user manager units, and CPUWeight=
+ settings are applied to the top-level user slice units (app.slice,
+ background.slice, session.slice). This provides a degree of resource
+ isolation between different user services competing for the CPU.
+
+ * Systemd can optionally do a full preset in the "first boot" condition
+ (instead of just enable-only). This behaviour is controlled by the
+ compile-time option -Dfirst-boot-full-preset=. Right now it defaults
+ to 'false', but the plan is to switch it to 'true' for the subsequent
+ release.
+
+ * Systemd will set the taint flag 'support-ended' if it detects that
+ the os image is past its end-of-support date.
+
+ * Two new settings ConditionCredential= and AssertCredential= can
+ be used to skip or fail units if a certain credential is not provided.
+
+ * ConditionMemory= accepts size suffixes.
+
+ * DefaultSmackProcessLabel= can be used in system.conf and user.conf
+ to specify the smack label to use when not specified in a unit file.
+
+ * DefaultDeviceTimeoutSec= can be used system.conf and user.conf
+ to specify the default timeout for devices.
+
+ * C.UTF-8 is used as the default locale if nothing else has been configured.
+
+ Changes in sd-boot, bootctl, and the Boot Loader Specification:
+
+ * The Boot Loader Specification has been cleaned up and clarified.
+ Various corner cases in version string comparisons have been fixed
+ (e.g. comparisons for empty strings). Boot counting is now part of
+ the main specification.
+
+ * New PCRs measurements are set during boot: PCR 11 for the the
+ kernel+initrd combo, PCR 13 for any sysext images.
+
+ * The UEFI monotonic boot counter is now included in the random seed,
+ providing some additional entropy.
+
+ * Booting in EFI mixed mode (a 64-bit kernel over 32-bit UEFI firmware)
+ is now supported.
+
+ * bootctl gained a bunch of new options: '--all-architectures' to
+ install binaries for all supported EFI architectures, '--root=' and
+ '--image=' options to operate on a directory or disk image, and
+ '--install-source=' to specify the source for binaries to install.
+
+ * The sd-boot stub exports a StubFeatures flag, which is used by
+ bootctl to show features supported by the stub that was used to boot.
+
+ Changes in the hardware database:
+
+ * 'systemd-hwdb query' now supports the '--root' option.
+
+ Changes in systemctl:
+
+ * systemctl now supports '--state' and '--type' options for the 'show'
+ and 'status' verbs.
+
+ * systemctl gained a new verb 'list-automounts' to list automount
+ points.
+
+ Changes in systemd-networkd:
+
+ * networkd can set Linux NetLabel labels for integration with the
+ network control in security modules via a new NetLabel= option.
+
+ * networkd gained new options NFTSet=, IPv4NFTSet=, IPv6NFTSet= that
+ take names of nft sets as arguments. It will automatically add rules
+ for the subnets configured for an interface to those sets.
+
+ * The RapidCommit= is (re-)introduced to enable faster configuration
+ via DHCPv6 (RFC 3315).
+
+ Changes in systemd-nspawn:
+
+ * The --bind= and --overlay= options now support relative paths.
+
+ Changes in libsystemd and other libraries:
+
+ * libsystemd now exports the sd-netlink interface that provides
+ functions to send/receive/parse netlink and rtnl messages.
+
+ * libsystemd now exports sd_bus_error_setfv (a convenience function for
+ setting bus errors), sd_id128_string_equal (a convenience function
+ for identifier comparisons), sd_bus_message_read_strv_extend (a
+ function to incrementally read string arrays).
+
+ * Private shared libraries (libsystemd-shared-nnn.so,
+ libsystemd-core-nnn.so) are now installed into arch-specific
+ directories to allow multi-arch installs.
+
+ Changes in other components:
+
+ * sysusers and tmpfiles configuration can now be provided via the
+ credential mechanism.
+
+ * tmpfiles can read file contents to write from a credential (and a new
+ modifier char '^' to specify that the argument is a credential name).
+ This mechanism is used to automatically populate /etc/motd, /etc/issue,
+ and /etc/hosts from credentials.
+
+ * systemd-analyze gained a new verb 'compare-versions' that implements
+ comparisons for versions strings (similarly to 'rpmdev-vercmp' and
+ 'dpkg --compare-versions').
+
+ * The pkgconfig and rpm macros files now export the directory for user
+ units as 'user_tmpfiles_dir' and '_user_tmpfilesdir'.
+
+ * Detection of Parallels and KubeVirt virtualization has been improved.
+
+ * os-release gained a new field SUPPORT_END=YYYY-MM-DD to inform the
+ user when their system will become unsupported.
+
+ * When performing suspend-then-hibernate, the system will estimate the
+ discharge rate and use that to set the delay until hibernation, and
+ will hibernate immediately instead of suspending when running from a
+ battery and the capacity is below 5%.
+
+ * systemd-sysctl gained a '--strict' option to fail when a sysctl
+ setting is unknown to the kernel.
+
+ * machinectl supports '--force' for the 'copy-to' and 'copy-from'
+ verbs.
+
+ * openssl is the default crypto backend for systemd-resolved. (gnutls
+ is still supported.)
+
+ Experimental features:
+
+ * BPF programs can now be compiled with bpf-gcc.
+
+ * sd-boot can automatically enroll SecureBoot keys from files found on
+ the ESP. This enrollment can be either automatic ('force' mode) or
+ controlled by the user ('manual' mode).
+
+ – Somewhere, sometime
+
+
CHANGES WITH 251:
Backwards-incompatible changes:
the seed from there already, if EFI_RNG_PROTOCOL is not implemented by
firmware.
+* sd-boot: include domain specific hash string in hash function for random seed
+ plus sizes of everything. also include DMI/SMBIOS blob
+
+* accept a random seed via DMI/SMBIOS vendor string that is credited to the
+ kernel RNG, as cheap alternative to virtio-rng
+
* sd-stub: invoke random seed logic the same way as in sd-boot, except if
random seed EFI variable is already set. That way, the variable set will be
set in all cases: if you just use sd-stub, or just sd-boot, or both.
three of these specific switches would set credential `foo` to `bar`.)
Passing credentials via the SMBIOS mechanism is typically preferable over
`fw_cfg` since it is faster and less specific to the chosen VMM
- implementation.
+ implementation. Moreover, `fw_cfg` has a 55 character limitation
+ on names passed that way. So some settings may not fit.
3. Credentials can also be passed into a system via the kernel command line,
via the `systemd.set-credential=` kernel command line option. Note though
#########################################
# Google Chromebooks
#########################################
-sensor:modalias:platform:cros-ec-accel:dmi:*:svnGOOGLE:*
- ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
-
-# caroline board (Samsung Chromebook Pro) reports itself as svnGoogle
-sensor:modalias:platform:cros-ec-accel:dmi:*:svnGoogle:pnCaroline*:*
- ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
-
-# Dell Inspiron Chromebook 14 2-in-1
-sensor:modalias:platform:cros-ec-accel:dmi:*svnGoogle:pnVayne*:*
- ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
-
-# nocturne board (Google Pixel Slate)
-sensor:modalias:platform:cros-ec-accel:dmi:*Google_Nocturne*:*
- ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
-# rammus board (Asus Chromebook Flip C433)
-sensor:modalias:platform:cros-ec-accel:dmi:*svnGoogle:pnRammus*:*
+# CrOS EC & kernel drivers internally correct for per-board sensor orientations,
+# but they return values in the inverse direction (Android & W3C specs vs HID).
+sensor:modalias:platform:cros-ec-accel:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
-# Lenovo ThinkPad C13 Yoga
-sensor:modalias:platform:cros-ec-accel:dmi:*svnGoogle:pnMorphius*:*
+sensor:modalias:platform:cros-ec-accel-legacy:*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
#########################################
# This file is part of systemd.
#
# Database for signal analyzers (protocol analyzers, logic analyzers,
-# oscilloscopes, multimeters, bench power supplies, etc.) that should
-# be accessible to the seat owner.
+# oscilloscopes, multimeters, bench power supplies, etc.) or just
+# anything that has to do with electronics and that should be
+# accessible to the seat owner.
#
# Permitted keys:
# Specify if a device is a signal analyzer
# ID_SIGNAL_ANALYZER=1|0
+###########################################################
+# Greaseweazle
+###########################################################
+# Greaseweazle
+usb:v1209p4D69*
+ ID_SIGNAL_ANALYZER=1
+
###########################################################
# Total Phase
###########################################################
interface org.freedesktop.oom1.Manager {
methods:
DumpByFileDescriptor(out h fd);
+ signals:
+ Killed(s cgroup,
+ s reason);
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
<variablelist class="dbus-method" generated="True" extra-ref="DumpByFileDescriptor()"/>
+ <variablelist class="dbus-signal" generated="True" extra-ref="Killed"/>
+
<!--End of Autogenerated section-->
<refsect2>
<title>Methods</title>
- <para>...</para>
+ <para><function>Killed</function> signal is sent when any cgroup is killed by oomd.</para>
+ <para>Note that more reasons will be added in the future, and the table below will be expanded accordingly.</para>
+ <table>
+ <title>Killing reasons</title>
+ <tgroup cols="2" align="left" colsep="1" rowsep="1">
+ <colspec colname="reason"/>
+ <colspec colname="description"/>
+ <thead>
+ <row>
+ <entry>Reason</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>memory-used</entry>
+ <entry>Application took too much memory and swap.</entry>
+ </row>
+ <row>
+ <entry>memory-pressure</entry>
+ <entry>Application took enough memory and swap to cause sufficient slowdown of other applications.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
</refsect2>
</refsect1>
</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--unlock-key-file=</option><replaceable>PATH</replaceable></term>
+
+ <listitem><para>Use a file instead of a password/passphrase read from stdin to unlock the volume.
+ Expects the PATH to the file containing your key to unlock the volume. Currently there is nothing like
+ <option>--key-file-offset=</option> or <option>--key-file-size=</option> so this file has to only
+ contain the full key.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--pkcs11-token-uri=</option><replaceable>URI</replaceable></term>
<variablelist>
<varlistentry>
<term><varname>ID_NET_NAME_ONBOARD=<replaceable>prefix</replaceable><constant>o</constant><replaceable>number</replaceable></varname></term>
+ <term><varname>ID_NET_NAME_ONBOARD=<replaceable>prefix</replaceable><constant>d</constant><replaceable>number</replaceable></varname></term>
<listitem><para>This name is set based on the numeric ordering information given by the firmware
- for on-board devices. The name consists of the prefix, letter <constant>o</constant>, and a number
- specified by the firmware. This is only available for PCI devices.</para>
+ for on-board devices. Different schemes are used depending on the fiemware type, as described in the table below.</para>
+
+ <table>
+ <title>Onboard naming schemes</title>
+
+ <tgroup cols='2'>
+ <thead>
+ <row>
+ <entry>Format</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry><replaceable>prefix</replaceable><constant>o</constant><replaceable>number</replaceable></entry>
+ <entry>PCI onboard index</entry>
+ </row>
+
+ <row>
+ <entry><replaceable>prefix</replaceable><constant>d</constant><replaceable>number</replaceable></entry>
+ <entry>Devicetree alias index</entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </table>
</listitem>
</varlistentry>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><constant>v252</constant></term>
+
+ <listitem><para>Added naming scheme for platform devices with devicetree aliases.</para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
<para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this
<term><varname>StartupCPUWeight=<replaceable>weight</replaceable></varname></term>
<listitem>
- <para>Assign the specified CPU time weight to the processes executed, if the unified control group
- hierarchy is used on the system. These options take an integer value and control the
- <literal>cpu.weight</literal> control group attribute. The allowed range is 1 to 10000. Defaults to
- 100. For details about this control group attribute, see <ulink
- url="https://docs.kernel.org/admin-guide/cgroup-v2.html">Control Groups v2</ulink>
- and <ulink url="https://docs.kernel.org/scheduler/sched-design-CFS.html">CFS
- Scheduler</ulink>. The available CPU time is split up among all units within one slice relative to
- their CPU time weight. A higher weight means more CPU time, a lower weight means less.</para>
+ <para>These options accept an integer value or a the special string "idle":</para>
+ <itemizedlist>
+ <listitem>
+ <para>If set to an integer value, assign the specified CPU time weight to the processes executed,
+ if the unified control group hierarchy is used on the system. These options control the
+ <literal>cpu.weight</literal> control group attribute. The allowed range is 1 to 10000. Defaults to
+ 100. For details about this control group attribute, see <ulink
+ url="https://docs.kernel.org/admin-guide/cgroup-v2.html">Control Groups v2</ulink>
+ and <ulink url="https://docs.kernel.org/scheduler/sched-design-CFS.html">CFS
+ Scheduler</ulink>. The available CPU time is split up among all units within one slice relative to
+ their CPU time weight. A higher weight means more CPU time, a lower weight means less.</para>
+ </listitem>
+ <listitem>
+ <para>If set to the special string "idle", mark the cgroup for "idle scheduling", which means
+ that it will get CPU resources only when there are no processes not marked in this way to execute in this
+ cgroup or its siblings. This setting corresponds to the <literal>cpu.idle</literal> cgroup attribute.</para>
+
+ <para>Note that this value only has an effect on cgroup-v2, for cgroup-v1 it is equivalent to the minimum weight.</para>
+ </listitem>
+ </itemizedlist>
<para>While <varname>StartupCPUWeight=</varname> applies to the startup and shutdown phases of the system,
<varname>CPUWeight=</varname> applies to normal runtime of the system, and if the former is not set also to
c_args = get_option('c_args')
# Our json library does not support -ffinite-math-only, which is enabled by -Ofast or -ffast-math.
-if (('-Ofast' in c_args or '-ffast-math' in c_args or '-ffinite-math-only' in c_args) and not ('-fno-finite-math-only' in c_args))
+if (('-Ofast' in c_args or '-ffast-math' in c_args or '-ffinite-math-only' in c_args) and '-fno-finite-math-only' not in c_args)
error('-Ofast, -ffast-math, or -ffinite-math-only is specified in c_args.')
endif
HostonlyInitrd=yes
# Prevent ASAN warnings when building the image
Environment=ASAN_OPTIONS=verify_asan_link_order=false
+OutputDirectory=mkosi.output
[Content]
BuildDirectory=mkosi.builddir
Cache=mkosi.cache
-InstallDirectory=mkosi.installdir
SourceFileTransferFinal=copy-git-others
[Host]
#
# Gabor Kelemen <kelemeng at gnome dot hu>, 2015, 2016.
# Balázs Úr <urbalazs at gmail dot com>, 2016.
+# Balázs Meskó <meskobalazs@mailbox.org>, 2022.
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-08 17:48+0100\n"
-"PO-Revision-Date: 2016-08-23 18:03+0100\n"
-"Last-Translator: Balázs Úr <urbalazs@gmail.com>\n"
-"Language-Team: Hungarian <openscope at googlegroups dot com>\n"
+"PO-Revision-Date: 2022-08-09 20:19+0000\n"
+"Last-Translator: Balázs Meskó <meskobalazs@mailbox.org>\n"
+"Language-Team: Hungarian <https://translate.fedoraproject.org/projects/"
+"systemd/master/hu/>\n"
"Language: hu\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"
-"X-Generator: Lokalize 2.0\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.13\n"
#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
#: src/home/org.freedesktop.home1.policy:13
msgid "Create a home area"
-msgstr ""
+msgstr "Saját terület létrehozása"
#: src/home/org.freedesktop.home1.policy:14
-#, fuzzy
-#| msgid "Authentication is required to reload the systemd state."
msgid "Authentication is required to create a user's home area."
-msgstr "Hitelesítés szükséges a systemd állapotának újratöltéséhez."
+msgstr "Hitelesítés szükséges a felhasználó saját területének létrehozásához."
#: src/home/org.freedesktop.home1.policy:23
msgid "Remove a home area"
-msgstr ""
+msgstr "Saját terület eltávolítása"
#: src/home/org.freedesktop.home1.policy:24
-#, fuzzy
-#| msgid "Authentication is required to reload the systemd state."
msgid "Authentication is required to remove a user's home area."
-msgstr "Hitelesítés szükséges a systemd állapotának újratöltéséhez."
+msgstr "Hitelesítés szükséges a felhasználó saját területének eltávolításához."
#: src/home/org.freedesktop.home1.policy:33
msgid "Check credentials of a home area"
-msgstr ""
+msgstr "Saját terület hitelesítő adatainak ellenőrzése"
#: src/home/org.freedesktop.home1.policy:34
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to manage active sessions, users and seats."
msgid ""
"Authentication is required to check credentials against a user's home area."
msgstr ""
-"Hitelesítés szükséges az aktív munkamenetek, felhasználók és munkaállomások "
-"kezeléséhez."
+"Hitelesítés szükséges a hitelesítő adatok a felhasználó saját területével "
+"való összevetéséhez."
#: src/home/org.freedesktop.home1.policy:43
msgid "Update a home area"
-msgstr ""
+msgstr "Saját terület frissítése"
#: src/home/org.freedesktop.home1.policy:44
-#, fuzzy
-#| msgid "Authentication is required to attach a device to a seat."
msgid "Authentication is required to update a user's home area."
-msgstr ""
-"Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy "
-"munkaállomáshoz"
+msgstr "Hitelesítés szükséges a felhasználó saját területének frissítéséhez."
#: src/home/org.freedesktop.home1.policy:53
msgid "Resize a home area"
-msgstr ""
+msgstr "Saját terület átméretezése"
#: src/home/org.freedesktop.home1.policy:54
-#, fuzzy
-#| msgid "Authentication is required to set a wall message"
msgid "Authentication is required to resize a user's home area."
-msgstr "Hitelesítés szükséges a falüzenet beállításához"
+msgstr "Hitelesítés szükséges a felhasználó saját területének átméretezéséhez."
#: src/home/org.freedesktop.home1.policy:63
msgid "Change password of a home area"
-msgstr ""
+msgstr "Saját terület hitelesítő adatainak módosítása"
#: src/home/org.freedesktop.home1.policy:64
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to manage active sessions, users and seats."
msgid ""
"Authentication is required to change the password of a user's home area."
msgstr ""
-"Hitelesítés szükséges az aktív munkamenetek, felhasználók és munkaállomások "
-"kezeléséhez."
+"Hitelesítés szükséges a felhasználó saját területének jelszavának "
+"módosításához."
#: src/hostname/org.freedesktop.hostname1.policy:20
msgid "Set hostname"
#: src/hostname/org.freedesktop.hostname1.policy:42
msgid "Authentication is required to set local machine information."
-msgstr "Hitelesítés szükséges a helyi gép információinak beállításához."
+msgstr "Hitelesítés szükséges a helyi gépinformációk beállításához."
#: src/hostname/org.freedesktop.hostname1.policy:51
msgid "Get product UUID"
-msgstr ""
+msgstr "Termék UUID-jának lekérése"
#: src/hostname/org.freedesktop.hostname1.policy:52
-#, fuzzy
-#| msgid "Authentication is required to reload '$(unit)'."
msgid "Authentication is required to get product UUID."
-msgstr "Hitelesítés szükséges a következő újratöltéséhez: „$(unit)”."
+msgstr "Hitelesítés szükséges a termék UUID-jának lekéréséhez."
#: src/import/org.freedesktop.import1.policy:22
msgid "Import a VM or container image"
-msgstr "VM vagy konténer lemezkép importálása"
+msgstr "VM vagy konténer lemezképének importálása"
#: src/import/org.freedesktop.import1.policy:23
msgid "Authentication is required to import a VM or container image"
-msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép importálásához."
+msgstr "Hitelesítés szükséges a VM vagy konténer lemezképének importálásához"
#: src/import/org.freedesktop.import1.policy:32
msgid "Export a VM or container image"
-msgstr "VM vagy konténer lemezkép exportálása"
+msgstr "VM vagy konténer lemezképének exportálása"
#: src/import/org.freedesktop.import1.policy:33
msgid "Authentication is required to export a VM or container image"
-msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép exportálásához."
+msgstr "Hitelesítés szükséges a VM vagy konténer lemezképének exportálásához"
#: src/import/org.freedesktop.import1.policy:42
msgid "Download a VM or container image"
-msgstr "VM vagy konténer lemezkép letöltése"
+msgstr "VM vagy konténer lemezképének letöltése"
#: src/import/org.freedesktop.import1.policy:43
msgid "Authentication is required to download a VM or container image"
-msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép letöltéséhez."
+msgstr "Hitelesítés szükséges a VM vagy konténer lemezképének letöltéséhez"
#: src/locale/org.freedesktop.locale1.policy:22
msgid "Set system locale"
-msgstr "Területi beállítás megadása"
+msgstr "Rendszer területi beállításának megadása"
#: src/locale/org.freedesktop.locale1.policy:23
msgid "Authentication is required to set the system locale."
#: src/locale/org.freedesktop.locale1.policy:33
msgid "Set system keyboard settings"
-msgstr "Rendszer billentyűzetbeállítások megadása"
+msgstr "Rendszer billentyűzetbeállításainak megadása"
#: src/locale/org.freedesktop.locale1.policy:34
msgid "Authentication is required to set the system keyboard settings."
#: src/login/org.freedesktop.login1.policy:22
msgid "Allow applications to inhibit system shutdown"
-msgstr "Alkalmazások meggátolhatják a rendszer leállítását"
+msgstr "Az alkalmazások meggátolhatják a rendszer leállítását"
#: src/login/org.freedesktop.login1.policy:23
msgid ""
#: src/login/org.freedesktop.login1.policy:33
msgid "Allow applications to delay system shutdown"
-msgstr "Alkalmazások késleltethetik a rendszer leállítását"
+msgstr "Az alkalmazások késleltethetik a rendszer leállítását"
#: src/login/org.freedesktop.login1.policy:34
msgid "Authentication is required for an application to delay system shutdown."
#: src/login/org.freedesktop.login1.policy:44
msgid "Allow applications to inhibit system sleep"
-msgstr "Alkalmazások meggátolhatják a rendszer altatását"
+msgstr "Az alkalmazások meggátolhatják a rendszer altatását"
#: src/login/org.freedesktop.login1.policy:45
msgid "Authentication is required for an application to inhibit system sleep."
#: src/login/org.freedesktop.login1.policy:55
msgid "Allow applications to delay system sleep"
-msgstr "Alkalmazások késleltethetik a rendszer altatását"
+msgstr "Az alkalmazások késleltethetik a rendszer altatását"
#: src/login/org.freedesktop.login1.policy:56
msgid "Authentication is required for an application to delay system sleep."
#: src/login/org.freedesktop.login1.policy:65
msgid "Allow applications to inhibit automatic system suspend"
-msgstr "Alkalmazások meggátolhatják a rendszer automatikus felfüggesztését"
+msgstr "Az alkalmazások meggátolhatják a rendszer automatikus felfüggesztését"
#: src/login/org.freedesktop.login1.policy:66
msgid ""
#: src/login/org.freedesktop.login1.policy:75
msgid "Allow applications to inhibit system handling of the power key"
msgstr ""
-"Alkalmazások meggátolhatják a bekapcsoló gomb rendszer általi kezelését"
+"Az alkalmazások meggátolhatják a bekapcsoló gomb rendszer általi kezelését"
#: src/login/org.freedesktop.login1.policy:76
msgid ""
#: src/login/org.freedesktop.login1.policy:86
msgid "Allow applications to inhibit system handling of the suspend key"
msgstr ""
-"Alkalmazások meggátolhatják a felfüggesztés gomb rendszer általi kezelését"
+"Az alkalmazások meggátolhatják a felfüggesztés gomb rendszer általi kezelését"
#: src/login/org.freedesktop.login1.policy:87
msgid ""
#: src/login/org.freedesktop.login1.policy:97
msgid "Allow applications to inhibit system handling of the hibernate key"
msgstr ""
-"Alkalmazások meggátolhatják a hibernálás gomb rendszer általi kezelését"
+"Az alkalmazások meggátolhatják a hibernálás gomb rendszer általi kezelését"
#: src/login/org.freedesktop.login1.policy:98
msgid ""
#: src/login/org.freedesktop.login1.policy:107
msgid "Allow applications to inhibit system handling of the lid switch"
-msgstr "Alkalmazások meggátolhatják a fedélkapcsoló rendszer általi kezelését"
+msgstr ""
+"Az alkalmazások meggátolhatják a fedélkapcsoló rendszer általi kezelését"
#: src/login/org.freedesktop.login1.policy:108
msgid ""
"kezelésének meggátlásához."
#: src/login/org.freedesktop.login1.policy:117
-#, fuzzy
-#| msgid "Allow applications to inhibit system handling of the power key"
msgid "Allow applications to inhibit system handling of the reboot key"
msgstr ""
-"Alkalmazások meggátolhatják a bekapcsoló gomb rendszer általi kezelését"
+"Az alkalmazások meggátolhatják az újraindítás gomb rendszer általi kezelését"
#: src/login/org.freedesktop.login1.policy:118
-#, fuzzy
-#| msgid ""
-#| "Authentication is required for an application to inhibit system handling "
-#| "of the power key."
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the reboot key."
msgstr ""
-"Hitelesítés szükséges egy alkalmazás számára a bekapcsoló gomb rendszer "
+"Hitelesítés szükséges egy alkalmazás számára az újraindítás gomb rendszer "
"általi kezelésének meggátlásához."
#: src/login/org.freedesktop.login1.policy:128
#: src/login/org.freedesktop.login1.policy:129
msgid "Explicit request is required to run programs as a non-logged-in user."
msgstr ""
-"Határozott kérés szükséges a programfuttatáshoz be nem jelentkezett "
-"felhasználóként."
+"Határozott kérés szükséges a be nem jelentkezett felhasználókénti "
+"programfuttatáshoz."
#: src/login/org.freedesktop.login1.policy:138
msgid "Allow non-logged-in users to run programs"
#: src/login/org.freedesktop.login1.policy:139
msgid "Authentication is required to run programs as a non-logged-in user."
msgstr ""
-"Hitelesítés szükséges a programfuttatáshoz be nem jelentkezett "
-"felhasználóként."
+"Hitelesítés szükséges a be nem jelentkezett felhasználókénti "
+"programfuttatáshoz."
#: src/login/org.freedesktop.login1.policy:148
msgid "Allow attaching devices to seats"
-msgstr "Eszközök csatolásának engedélyezése munkaállomásokhoz"
+msgstr "Eszközök munkaállomásokhoz csatolásának engedélyezése"
#: src/login/org.freedesktop.login1.policy:149
msgid "Authentication is required to attach a device to a seat."
msgstr ""
-"Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy "
-"munkaállomáshoz"
+"Hitelesítés szükséges az eszköz munkaállomáshoz csatolásának "
+"engedélyezéséhez."
#: src/login/org.freedesktop.login1.policy:159
msgid "Flush device to seat attachments"
#: src/login/org.freedesktop.login1.policy:213
msgid "Reboot the system while other users are logged in"
-msgstr "A rendszer újraindítása mialatt be vannak jelentkezve más felhasználók"
+msgstr "A rendszer újraindítása miközben be vannak jelentkezve más felhasználók"
#: src/login/org.freedesktop.login1.policy:214
msgid ""
"ennek meggátlását kérte."
#: src/login/org.freedesktop.login1.policy:235
-#, fuzzy
-#| msgid "Hibernate the system"
msgid "Halt the system"
-msgstr "A rendszer hibernálása"
+msgstr "A rendszer leállítása"
#: src/login/org.freedesktop.login1.policy:236
-#, fuzzy
-#| msgid "Authentication is required to hibernate the system."
msgid "Authentication is required to halt the system."
-msgstr "Hitelesítés szükséges a rendszer hibernálásához."
+msgstr "Hitelesítés szükséges a rendszer leállításához."
#: src/login/org.freedesktop.login1.policy:246
-#, fuzzy
-#| msgid "Hibernate the system while other users are logged in"
msgid "Halt the system while other users are logged in"
-msgstr "A rendszer hibernálása mialatt be vannak jelentkezve más felhasználók"
+msgstr "A rendszer leállítása miközben más felhasználók be vannak jelentkezve"
#: src/login/org.freedesktop.login1.policy:247
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to hibernate the system while other users are "
-#| "logged in."
msgid ""
"Authentication is required to halt the system while other users are logged "
"in."
msgstr ""
-"Hitelesítés szükséges a rendszer hibernálásához miközben be vannak "
-"jelentkezve más felhasználók."
+"Hitelesítés szükséges a rendszer leállításához miközben más felhasználók be "
+"vannak jelentkezve."
#: src/login/org.freedesktop.login1.policy:257
-#, fuzzy
-#| msgid "Hibernate the system while an application is inhibiting this"
msgid "Halt the system while an application is inhibiting this"
-msgstr "A rendszer hibernálása miközben egy alkalmazás ennek meggátlását kérte"
+msgstr "A rendszer leállítása miközben egy alkalmazás ennek meggátlását kérte"
#: src/login/org.freedesktop.login1.policy:258
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to hibernate the system while an application "
-#| "is inhibiting this."
msgid ""
"Authentication is required to halt the system while an application is "
"inhibiting this."
msgstr ""
-"Hitelesítés szükséges a rendszer hibernálásához miközben egy alkalmazás "
-"ennek meggátlását kérte."
+"Hitelesítés szükséges a rendszer leállításához miközben egy alkalmazás ennek "
+"meggátlását kérte."
#: src/login/org.freedesktop.login1.policy:268
msgid "Suspend the system"
#: src/login/org.freedesktop.login1.policy:310
msgid "Hibernate the system while other users are logged in"
-msgstr "A rendszer hibernálása mialatt be vannak jelentkezve más felhasználók"
+msgstr "A rendszer hibernálása miközben be vannak jelentkezve más felhasználók"
#: src/login/org.freedesktop.login1.policy:311
msgid ""
#: src/login/org.freedesktop.login1.policy:352
msgid "Set the reboot \"reason\" in the kernel"
-msgstr ""
+msgstr "Az újraindítás „okának” beállítása a kernelben"
#: src/login/org.freedesktop.login1.policy:353
-#, fuzzy
-#| msgid "Authentication is required to set the system timezone."
msgid "Authentication is required to set the reboot \"reason\" in the kernel."
-msgstr "Hitelesítés szükséges a rendszer időzónájának beállításához."
+msgstr ""
+"Hitelesítés szükséges a rendszer újraindítási „okának” beállításához a "
+"kernelben."
#: src/login/org.freedesktop.login1.policy:363
-#, fuzzy
-#| msgid "Allow indication to the firmware to boot to setup interface"
msgid "Indicate to the firmware to boot to setup interface"
-msgstr "A firmware-nek jelezhető, hogy a beállítófelületet bootolja"
+msgstr ""
+"Jelzés a firmware számára, hogy a beállítófelületet indítsa el "
+"rendszerindításkor"
#: src/login/org.freedesktop.login1.policy:364
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
msgstr ""
-"Hitelesítés szükséges a firmware-nek jelzéshez, hogy a beállítófelületet "
-"bootolja"
+"Hitelesítés szükséges, hogy a firmware a beállítófelületet indítsa el "
+"rendszerindításkor."
#: src/login/org.freedesktop.login1.policy:374
msgid "Indicate to the boot loader to boot to the boot loader menu"
msgstr ""
+"Jelzés a rendszerbetöltő számára, hogy a rendszerbetöltő menüt indítsa el "
+"rendszerindításkor"
#: src/login/org.freedesktop.login1.policy:375
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to indicate to the firmware to boot to setup "
-#| "interface."
msgid ""
"Authentication is required to indicate to the boot loader to boot to the "
"boot loader menu."
msgstr ""
-"Hitelesítés szükséges a firmware-nek jelzéshez, hogy a beállítófelületet "
-"bootolja"
+"Hitelesítés szükséges, hogy a firmware a rendszerbetöltő menüt indítsa el "
+"rendszerindításkor."
#: src/login/org.freedesktop.login1.policy:385
msgid "Indicate to the boot loader to boot a specific entry"
msgstr ""
+"Jelzés a rendszerbetöltő számára, hogy egy adott bejegyzést indítson el "
+"rendszerindításkor"
#: src/login/org.freedesktop.login1.policy:386
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to indicate to the firmware to boot to setup "
-#| "interface."
msgid ""
"Authentication is required to indicate to the boot loader to boot into a "
"specific boot loader entry."
msgstr ""
-"Hitelesítés szükséges a firmware-nek jelzéshez, hogy a beállítófelületet "
-"bootolja"
+"Hitelesítés szükséges, hogy a rendszerbetöltő egy adott bejegyzést indítson "
+"el rendszerindításkor."
#: src/login/org.freedesktop.login1.policy:396
msgid "Set a wall message"
#: src/login/org.freedesktop.login1.policy:406
msgid "Change Session"
-msgstr ""
+msgstr "Munkamenet módosítása"
#: src/login/org.freedesktop.login1.policy:407
-#, fuzzy
-#| msgid "Authentication is required to set the local hostname."
msgid "Authentication is required to change the virtual terminal."
-msgstr "Hitelesítés szükséges a helyi gépnév beállításához."
+msgstr "Hitelesítés szükséges a virtuális terminál módosításához."
#: src/machine/org.freedesktop.machine1.policy:22
msgid "Log into a local container"
#: src/machine/org.freedesktop.machine1.policy:23
msgid "Authentication is required to log into a local container."
-msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe."
+msgstr "Hitelesítés szükséges a helyi konténerbe történő bejelentkezéshez."
#: src/machine/org.freedesktop.machine1.policy:32
msgid "Log into the local host"
#: src/machine/org.freedesktop.machine1.policy:33
msgid "Authentication is required to log into the local host."
-msgstr "Hitelesítés szükséges a bejelentkezéshez a helyi gépre."
+msgstr "Hitelesítés szükséges a helyi gépre történtő bejelentkezéshez."
#: src/machine/org.freedesktop.machine1.policy:42
msgid "Acquire a shell in a local container"
#: src/machine/org.freedesktop.machine1.policy:95
msgid "Manage local virtual machine and container images"
-msgstr "Helyi virtuális gép és konténer lemezképek kezelése"
+msgstr "Helyi virtuális gépek és konténerek lemezképeinek kezelése"
#: src/machine/org.freedesktop.machine1.policy:96
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
msgstr ""
-"Hitelesítés szükséges a helyi virtuális gép és konténer lemezképek "
+"Hitelesítés szükséges a helyi virtuális gépek és konténerek lemezképeinek "
"kezeléséhez."
#: src/network/org.freedesktop.network1.policy:22
msgid "Set NTP servers"
-msgstr ""
+msgstr "NTP-kiszolgálók beállítása"
#: src/network/org.freedesktop.network1.policy:23
-#, fuzzy
-#| msgid "Authentication is required to set the system time."
msgid "Authentication is required to set NTP servers."
-msgstr "Hitelesítés szükséges a rendszeridő beállításához."
+msgstr "Hitelesítés szükséges az NTP-kiszolgálók beállításához."
#: src/network/org.freedesktop.network1.policy:33
#: src/resolve/org.freedesktop.resolve1.policy:44
msgid "Set DNS servers"
-msgstr ""
+msgstr "DNS-kiszolgálók beállítása"
#: src/network/org.freedesktop.network1.policy:34
#: src/resolve/org.freedesktop.resolve1.policy:45
-#, fuzzy
-#| msgid "Authentication is required to set the system time."
msgid "Authentication is required to set DNS servers."
-msgstr "Hitelesítés szükséges a rendszeridő beállításához."
+msgstr "Hitelesítés szükséges a DNS-kiszolgálók beállításához."
#: src/network/org.freedesktop.network1.policy:44
#: src/resolve/org.freedesktop.resolve1.policy:55
msgid "Set domains"
-msgstr ""
+msgstr "Domainek beállítása"
#: src/network/org.freedesktop.network1.policy:45
#: src/resolve/org.freedesktop.resolve1.policy:56
-#, fuzzy
-#| msgid "Authentication is required to stop '$(unit)'."
msgid "Authentication is required to set domains."
-msgstr "Hitelesítés szükséges a következő leállításához: „$(unit)”."
+msgstr "Hitelesítés szükséges a domainek beállításához."
#: src/network/org.freedesktop.network1.policy:55
#: src/resolve/org.freedesktop.resolve1.policy:66
msgid "Set default route"
-msgstr ""
+msgstr "Alapértelmezett hálózati útvonal beállítása"
#: src/network/org.freedesktop.network1.policy:56
#: src/resolve/org.freedesktop.resolve1.policy:67
-#, fuzzy
-#| msgid "Authentication is required to set the local hostname."
msgid "Authentication is required to set default route."
-msgstr "Hitelesítés szükséges a helyi gépnév beállításához."
+msgstr ""
+"Hitelesítés szükséges az alapértelmezett hálózati útvonal beállításához."
#: src/network/org.freedesktop.network1.policy:66
#: src/resolve/org.freedesktop.resolve1.policy:77
msgid "Enable/disable LLMNR"
-msgstr ""
+msgstr "LLMNR engedélyezése/letiltása"
#: src/network/org.freedesktop.network1.policy:67
#: src/resolve/org.freedesktop.resolve1.policy:78
-#, fuzzy
-#| msgid "Authentication is required to hibernate the system."
msgid "Authentication is required to enable or disable LLMNR."
-msgstr "Hitelesítés szükséges a rendszer hibernálásához."
+msgstr "Hitelesítés szükséges az LLMNR engedélyezéséhez vagy kikapcsolásához."
#: src/network/org.freedesktop.network1.policy:77
#: src/resolve/org.freedesktop.resolve1.policy:88
msgid "Enable/disable multicast DNS"
-msgstr ""
+msgstr "Multicast DNS engedélyezése/letiltása"
#: src/network/org.freedesktop.network1.policy:78
#: src/resolve/org.freedesktop.resolve1.policy:89
-#, fuzzy
-#| msgid "Authentication is required to log into the local host."
msgid "Authentication is required to enable or disable multicast DNS."
-msgstr "Hitelesítés szükséges a bejelentkezéshez a helyi gépre."
+msgstr ""
+"Hitelesítés szükséges a multicast DNS engedélyezéséhez vagy kikapcsolásához."
#: src/network/org.freedesktop.network1.policy:88
#: src/resolve/org.freedesktop.resolve1.policy:99
msgid "Enable/disable DNS over TLS"
-msgstr ""
+msgstr "TLS feletti DNS engedélyezése/letiltása"
#: src/network/org.freedesktop.network1.policy:89
#: src/resolve/org.freedesktop.resolve1.policy:100
-#, fuzzy
-#| msgid "Authentication is required to set the local hostname."
msgid "Authentication is required to enable or disable DNS over TLS."
-msgstr "Hitelesítés szükséges a helyi gépnév beállításához."
+msgstr ""
+"Hitelesítés szükséges a TLS feletti DNS engedélyezéséhez vagy "
+"kikapcsolásához."
#: src/network/org.freedesktop.network1.policy:99
#: src/resolve/org.freedesktop.resolve1.policy:110
msgid "Enable/disable DNSSEC"
-msgstr ""
+msgstr "DNSSEC engedélyezése/letiltása"
#: src/network/org.freedesktop.network1.policy:100
#: src/resolve/org.freedesktop.resolve1.policy:111
-#, fuzzy
-#| msgid "Authentication is required to hibernate the system."
msgid "Authentication is required to enable or disable DNSSEC."
-msgstr "Hitelesítés szükséges a rendszer hibernálásához."
+msgstr "Hitelesítés szükséges a DNSSEC engedélyezéséhez vagy kikapcsolásához."
#: src/network/org.freedesktop.network1.policy:110
#: src/resolve/org.freedesktop.resolve1.policy:121
msgid "Set DNSSEC Negative Trust Anchors"
-msgstr ""
+msgstr "DNSSEC Negative Trust Anchor beállítása"
#: src/network/org.freedesktop.network1.policy:111
#: src/resolve/org.freedesktop.resolve1.policy:122
-#, fuzzy
-#| msgid "Authentication is required to set the system locale."
msgid "Authentication is required to set DNSSEC Negative Trust Anchors."
-msgstr "Hitelesítés szükséges a rendszer területi beállításainak megadásához."
+msgstr "Hitelestés szükséges a DNSSEC Negative Trust Anchor beállításához."
#: src/network/org.freedesktop.network1.policy:121
msgid "Revert NTP settings"
-msgstr ""
+msgstr "NTP-beállítások visszaállítása"
#: src/network/org.freedesktop.network1.policy:122
-#, fuzzy
-#| msgid "Authentication is required to set the system time."
msgid "Authentication is required to reset NTP settings."
-msgstr "Hitelesítés szükséges a rendszeridő beállításához."
+msgstr "Hitelesítés szükséges az NTP-beállítások visszaállításához."
#: src/network/org.freedesktop.network1.policy:132
msgid "Revert DNS settings"
-msgstr ""
+msgstr "DNS-beállítások visszaállítása"
#: src/network/org.freedesktop.network1.policy:133
-#, fuzzy
-#| msgid "Authentication is required to set the system time."
msgid "Authentication is required to reset DNS settings."
-msgstr "Hitelesítés szükséges a rendszeridő beállításához."
+msgstr "Hitelesítés szükséges a DNS-beállítások visszaállításához."
#: src/network/org.freedesktop.network1.policy:143
msgid "DHCP server sends force renew message"
-msgstr ""
+msgstr "A DHCP-kiszolgáló kényszerített megújítási üzenetet küld"
#: src/network/org.freedesktop.network1.policy:144
-#, fuzzy
-#| msgid "Authentication is required to set a wall message"
msgid "Authentication is required to send force renew message."
-msgstr "Hitelesítés szükséges a falüzenet beállításához"
+msgstr "Hitelesítés szükséges a kényszerített megújítási üzenetet küldéséhez."
#: src/network/org.freedesktop.network1.policy:154
msgid "Renew dynamic addresses"
-msgstr ""
+msgstr "Dinamikus címke megújítása"
#: src/network/org.freedesktop.network1.policy:155
-#, fuzzy
-#| msgid "Authentication is required to set a wall message"
msgid "Authentication is required to renew dynamic addresses."
-msgstr "Hitelesítés szükséges a falüzenet beállításához"
+msgstr "Hitelesítés szükséges a dinamikus címke megújításához."
#: src/network/org.freedesktop.network1.policy:165
msgid "Reload network settings"
-msgstr ""
+msgstr "Hálózati beállítások újratöltése"
#: src/network/org.freedesktop.network1.policy:166
-#, fuzzy
-#| msgid "Authentication is required to reload the systemd state."
msgid "Authentication is required to reload network settings."
-msgstr "Hitelesítés szükséges a systemd állapotának újratöltéséhez."
+msgstr "Hitelesítés szükséges a hálózati beállítások újratöltéséhez."
#: src/network/org.freedesktop.network1.policy:176
msgid "Reconfigure network interface"
-msgstr ""
+msgstr "Hálózati csatoló újrakonfigurálása"
#: src/network/org.freedesktop.network1.policy:177
-#, fuzzy
-#| msgid "Authentication is required to reboot the system."
msgid "Authentication is required to reconfigure network interface."
-msgstr "Hitelesítés szükséges a rendszer újraindításához."
+msgstr "Hitelesítés szükséges a hálózati csatoló újrakonfigurálásához."
#: src/portable/org.freedesktop.portable1.policy:13
msgid "Inspect a portable service image"
-msgstr ""
+msgstr "Hordozható szolgáltatás lemezképének vizsgálata"
#: src/portable/org.freedesktop.portable1.policy:14
-#, fuzzy
-#| msgid "Authentication is required to import a VM or container image"
msgid "Authentication is required to inspect a portable service image."
-msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép importálásához."
+msgstr ""
+"Hitelesítés szükséges a hordozható szolgáltatás lemezképének vizsgálatához."
#: src/portable/org.freedesktop.portable1.policy:23
msgid "Attach or detach a portable service image"
-msgstr ""
+msgstr "Hordozható szolgáltatás lemezképének csatolása vagy leválasztása"
#: src/portable/org.freedesktop.portable1.policy:24
-#, fuzzy
-#| msgid "Authentication is required to attach a device to a seat."
msgid ""
"Authentication is required to attach or detach a portable service image."
msgstr ""
-"Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy "
-"munkaállomáshoz"
+"Hitelesítés szükséges a hordozható szolgáltatás lemezképének csatolásához "
+"vagy leválasztásához."
#: src/portable/org.freedesktop.portable1.policy:34
msgid "Delete or modify portable service image"
-msgstr ""
+msgstr "Hordozható szolgáltatás lemezképének törlése vagy módosítása"
#: src/portable/org.freedesktop.portable1.policy:35
-#, fuzzy
-#| msgid "Authentication is required to download a VM or container image"
msgid ""
"Authentication is required to delete or modify a portable service image."
-msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép letöltéséhez."
+msgstr ""
+"Hitelesítés szükséges a hordozható szolgáltatás lemezképének törléséhez vagy "
+"módosításához."
#: src/resolve/org.freedesktop.resolve1.policy:22
msgid "Register a DNS-SD service"
-msgstr ""
+msgstr "DNS-SD szolgáltatás regisztrálása"
#: src/resolve/org.freedesktop.resolve1.policy:23
-#, fuzzy
-#| msgid "Authentication is required to set a wall message"
msgid "Authentication is required to register a DNS-SD service"
-msgstr "Hitelesítés szükséges a falüzenet beállításához"
+msgstr "Hitelesítés szükséges a DNS-SD szolgáltatás regisztrálásához"
#: src/resolve/org.freedesktop.resolve1.policy:33
msgid "Unregister a DNS-SD service"
-msgstr ""
+msgstr "DNS-SD szolgáltatás kiregisztrálása"
#: src/resolve/org.freedesktop.resolve1.policy:34
-#, fuzzy
-#| msgid "Authentication is required to set a wall message"
msgid "Authentication is required to unregister a DNS-SD service"
-msgstr "Hitelesítés szükséges a falüzenet beállításához"
+msgstr "Hitelesítés szükséges a DNS-SD szolgáltatás kiregisztrálásához"
#: src/resolve/org.freedesktop.resolve1.policy:132
msgid "Revert name resolution settings"
-msgstr ""
+msgstr "Névfeloldási beállítások visszaállítása"
#: src/resolve/org.freedesktop.resolve1.policy:133
-#, fuzzy
-#| msgid "Authentication is required to set the system keyboard settings."
msgid "Authentication is required to reset name resolution settings."
-msgstr ""
-"Hitelesítés szükséges a rendszer billentyűzetbeállításainak megadásához."
+msgstr "Hitelesítés szükséges a névfeloldási beállítások visszaállításához."
#: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time"
msgstr "Hitelesítés szükséges a következő újraindításához: „$(unit)”."
#: src/core/dbus-unit.c:535
-#, fuzzy
-#| msgid "Authentication is required to set properties on '$(unit)'."
msgid ""
"Authentication is required to send a UNIX signal to the processes of "
"'$(unit)'."
msgstr ""
-"Hitelesítés szükséges a következő tulajdonságainak beállításához: „$(unit)”."
+"Hitelesítés szükséges a UNIX szignál elküldéséhez a következő folyamatai "
+"számára: „$(unit)”."
#: src/core/dbus-unit.c:566
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
"Hitelesítés szükséges a következő tulajdonságainak beállításához: „$(unit)”."
#: src/core/dbus-unit.c:708
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgid ""
"Authentication is required to delete files and directories associated with "
"'$(unit)'."
msgstr ""
-"Hitelesítés szükséges a következő „sikertelen” állapotának törléséhez: "
-"„$(unit)”."
+"Hitelesítés szükséges a következővel kapcsolatos fájlok és könyvtárak "
+"törléséhez: „$(unit)”."
#: src/core/dbus-unit.c:757
-#, fuzzy
-#| msgid ""
-#| "Authentication is required to reset the \"failed\" state of '$(unit)'."
msgid ""
"Authentication is required to freeze or thaw the processes of '$(unit)' unit."
msgstr ""
-"Hitelesítés szükséges a következő „sikertelen” állapotának törléséhez: "
+"Hitelesítés szükséges a következő egység folyamatainak befagyasztásához: "
"„$(unit)”."
#~ msgid "Authentication is required to kill '$(unit)'."
# Protocol analyzers
ENV{ID_SIGNAL_ANALYZER}=="?*", ENV{DEVTYPE}=="usb_device", TAG+="uaccess"
+ENV{ID_SIGNAL_ANALYZER}=="?*", KERNEL=="ttyACM[0-9]*", TAG+="uaccess"
# rfkill / radio killswitches
KERNEL=="rfkill", SUBSYSTEM=="misc", TAG+="uaccess"
/* Special values for all weight knobs on unified hierarchy */
#define CGROUP_WEIGHT_INVALID UINT64_MAX
+#define CGROUP_WEIGHT_IDLE UINT64_C(0)
#define CGROUP_WEIGHT_MIN UINT64_C(1)
#define CGROUP_WEIGHT_MAX UINT64_C(10000)
#define CGROUP_WEIGHT_DEFAULT UINT64_C(100)
config_add_entry(config, entry);
if (config->secure_boot_enroll == ENROLL_FORCE && strcaseeq16(dirent->FileName, u"auto"))
- /* if we auto enroll sucessfully this call does not return, if it fails we still
+ /* if we auto enroll successfully this call does not return, if it fails we still
* want to add other potential entries to the menu */
secure_boot_enroll_at(root_dir, entry->path);
}
efi_crt0,
]
-possible_link_flags = [
- '-Wl,--no-warn-execstack',
- '-Wl,--no-warn-rwx-segments',
-]
-efi_ldflags += cc.get_supported_link_arguments(possible_link_flags)
+foreach arg : ['-Wl,--no-warn-execstack',
+ '-Wl,--no-warn-rwx-segments']
+ # We need to check the correct linker for supported args. This is what
+ # cc.has_multi_link_arguments() is for, but it helpfully overrides our
+ # choice of linker by putting its own -fuse-ld= arg after ours.
+ if run_command('bash', '-c',
+ 'exec "$@" -x c -o/dev/null <(echo "int main(void){return 0;}")' +
+ ' -fuse-ld=' + efi_ld + ' -Wl,--fatal-warnings ' + arg,
+ 'bash', cc.cmd_array(),
+ check : false).returncode() == 0
+ efi_ldflags += arg
+ endif
+endforeach
if efi_arch[1] in ['aarch64', 'arm', 'riscv64']
efi_ldflags += ['-shared']
}
/* if we are not in secure boot mode, or none was provided, accept a custom command line and replace
- * the built-in one. We also do a superficial check whether first chararacter of passed command line
+ * the built-in one. We also do a superficial check whether first character of passed command line
* is printable character (for compat with some Dell systems which fill in garbage?). */
if ((!secure_boot_enabled() || cmdline_len == 0) &&
loaded_image->LoadOptionsSize > 0 &&
static void cgroup_apply_unified_cpu_weight(Unit *u, uint64_t weight) {
char buf[DECIMAL_STR_MAX(uint64_t) + 2];
+ if (weight == CGROUP_WEIGHT_IDLE)
+ return;
xsprintf(buf, "%" PRIu64 "\n", weight);
(void) set_attribute_and_warn(u, "cpu", "cpu.weight", buf);
}
+static void cgroup_apply_unified_cpu_idle(Unit *u, uint64_t weight) {
+ int r;
+ bool is_idle;
+ const char *idle_val;
+
+ is_idle = weight == CGROUP_WEIGHT_IDLE;
+ idle_val = one_zero(is_idle);
+ r = cg_set_attribute("cpu", u->cgroup_path, "cpu.idle", idle_val);
+ if (r < 0 && (r != -ENOENT || is_idle))
+ log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%s': %m",
+ "cpu.idle", empty_to_root(u->cgroup_path), idle_val);
+}
+
static void cgroup_apply_unified_cpu_quota(Unit *u, usec_t quota, usec_t period) {
char buf[(DECIMAL_STR_MAX(usec_t) + 1) * 2 + 1];
}
static uint64_t cgroup_cpu_weight_to_shares(uint64_t weight) {
+ /* we don't support idle in cgroupv1 */
+ if (weight == CGROUP_WEIGHT_IDLE)
+ return CGROUP_CPU_SHARES_MIN;
+
return CLAMP(weight * CGROUP_CPU_SHARES_DEFAULT / CGROUP_WEIGHT_DEFAULT,
CGROUP_CPU_SHARES_MIN, CGROUP_CPU_SHARES_MAX);
}
} else
weight = CGROUP_WEIGHT_DEFAULT;
+ cgroup_apply_unified_cpu_idle(u, weight);
cgroup_apply_unified_cpu_weight(u, weight);
cgroup_apply_unified_cpu_quota(u, c->cpu_quota_per_sec_usec, c->cpu_quota_period_usec);
}
DISABLE_WARNING_TYPE_LIMITS;
-BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight, CGROUP_MASK_CPU, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID);
BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID);
BUS_DEFINE_SET_CGROUP_LIMIT(swap, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
REENABLE_WARNING;
+static int bus_cgroup_set_cpu_weight(
+ Unit *u,
+ const char *name,
+ uint64_t *p,
+ sd_bus_message *message,
+ UnitWriteFlags flags,
+ sd_bus_error *error) {
+ uint64_t v;
+ int r;
+ assert(p);
+ r = sd_bus_message_read(message, "t", &v);
+ if (r < 0)
+ return r;
+ if (!CGROUP_WEIGHT_IS_OK(v) && v != CGROUP_WEIGHT_IDLE)
+ return sd_bus_error_setf(
+ error, SD_BUS_ERROR_INVALID_ARGS, "Value specified in %s is out of range", name);
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ *p = v;
+ unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
+ if (v == CGROUP_WEIGHT_INVALID)
+ unit_write_settingf(u, flags, name, "%s=", name);
+ else if (v == CGROUP_WEIGHT_IDLE)
+ unit_write_settingf(u, flags, name, "%s=idle", name);
+ else
+ unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, v);
+ }
+ return 1;
+}
+
static int bus_cgroup_set_tasks_max(
Unit *u,
const char *name,
if (d->state != DEVICE_DEAD)
/* So here's a special hack, to compensate for the fact that the udev database's reload cycles are not
* synchronized with our own reload cycles: when we detect that the SYSTEMD_WANTS property of a device
- * changes while the device unit is already up, let's manually trigger any new units listed in it not
- * seen before. This typically happens during the boot-time switch root transition, as udev devices
- * will generally already be up in the initrd, but SYSTEMD_WANTS properties get then added through udev
- * rules only available on the host system, and thus only when the initial udev coldplug trigger runs.
+ * changes while the device unit is already up, let's skip to trigger units that were already listed
+ * and are active, and start units otherwise. This typically happens during the boot-time switch root
+ * transition, as udev devices will generally already be up in the initrd, but SYSTEMD_WANTS properties
+ * get then added through udev rules only available on the host system, and thus only when the initial
+ * udev coldplug trigger runs.
*
* We do this only if the device has been up already when we parse this, as otherwise the usual
* dependency logic that is run from the dead → plugged transition will trigger these deps. */
STRV_FOREACH(i, added) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- if (strv_contains(d->wants_property, *i)) /* Was this unit already listed before? */
- continue;
+ if (strv_contains(d->wants_property, *i)) {
+ Unit *v;
+
+ v = manager_get_unit(u->manager, *i);
+ if (v && UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(v)))
+ continue; /* The unit was already listed and is running. */
+ }
r = manager_add_job_by_name(u->manager, JOB_START, *i, JOB_FAIL, NULL, &error, NULL);
if (r < 0)
{{type}}.AllowedMemoryNodes, config_parse_allowed_cpuset, 0, offsetof({{type}}, cgroup_context.cpuset_mems)
{{type}}.StartupAllowedMemoryNodes, config_parse_allowed_cpuset, 0, offsetof({{type}}, cgroup_context.startup_cpuset_mems)
{{type}}.CPUAccounting, config_parse_bool, 0, offsetof({{type}}, cgroup_context.cpu_accounting)
-{{type}}.CPUWeight, config_parse_cg_weight, 0, offsetof({{type}}, cgroup_context.cpu_weight)
-{{type}}.StartupCPUWeight, config_parse_cg_weight, 0, offsetof({{type}}, cgroup_context.startup_cpu_weight)
+{{type}}.CPUWeight, config_parse_cg_cpu_weight, 0, offsetof({{type}}, cgroup_context.cpu_weight)
+{{type}}.StartupCPUWeight, config_parse_cg_cpu_weight, 0, offsetof({{type}}, cgroup_context.startup_cpu_weight)
{{type}}.CPUShares, config_parse_cpu_shares, 0, offsetof({{type}}, cgroup_context.cpu_shares)
{{type}}.StartupCPUShares, config_parse_cpu_shares, 0, offsetof({{type}}, cgroup_context.startup_cpu_shares)
{{type}}.CPUQuota, config_parse_cpu_quota, 0, offsetof({{type}}, cgroup_context)
DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_ip_tos, ip_tos, int, -1, "Failed to parse IP TOS value");
DEFINE_CONFIG_PARSE_PTR(config_parse_blockio_weight, cg_blkio_weight_parse, uint64_t, "Invalid block IO weight");
DEFINE_CONFIG_PARSE_PTR(config_parse_cg_weight, cg_weight_parse, uint64_t, "Invalid weight");
+DEFINE_CONFIG_PARSE_PTR(config_parse_cg_cpu_weight, cg_cpu_weight_parse, uint64_t, "Invalid CPU weight");
DEFINE_CONFIG_PARSE_PTR(config_parse_cpu_shares, cg_cpu_shares_parse, uint64_t, "Invalid CPU shares");
DEFINE_CONFIG_PARSE_PTR(config_parse_exec_mount_flags, mount_propagation_flags_from_string, unsigned long, "Failed to parse mount flag");
DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_numa_policy, mpol, int, -1, "Invalid NUMA policy type");
{ config_parse_restrict_filesystems, "FILESYSTEMS" },
{ config_parse_cpu_shares, "SHARES" },
{ config_parse_cg_weight, "WEIGHT" },
+ { config_parse_cg_cpu_weight, "CPUWEIGHT" },
{ config_parse_memory_limit, "LIMIT" },
{ config_parse_device_allow, "DEVICE" },
{ config_parse_device_policy, "POLICY" },
CONFIG_PARSER_PROTOTYPE(config_parse_unset_environ);
CONFIG_PARSER_PROTOTYPE(config_parse_unit_slice);
CONFIG_PARSER_PROTOTYPE(config_parse_cg_weight);
+CONFIG_PARSER_PROTOTYPE(config_parse_cg_cpu_weight);
CONFIG_PARSER_PROTOTYPE(config_parse_cpu_shares);
CONFIG_PARSER_PROTOTYPE(config_parse_memory_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_tasks_max);
config_item_table_lookup, items,
CONFIG_PARSE_WARN,
NULL,
+ NULL,
NULL);
/* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we use
(void) unit_reset_accounting(u);
/* We check only for User= option to keep behavior consistent with logic for service units,
- * i.e. having 'Delegate=true Group=foo' w/o specifing User= has no effect. */
+ * i.e. having 'Delegate=true Group=foo' w/o specifying User= has no effect. */
if (s->user && unit_cgroup_delegate(u))
return scope_enter_start_chown(s);
unit_prune_cgroup(u);
}
+static void scope_notify_cgroup_oom_event(Unit *u, bool managed_oom) {
+ Scope *s = SCOPE(u);
+
+ if (managed_oom)
+ log_unit_debug(u, "Process(es) of control group were killed by systemd-oomd.");
+ else
+ log_unit_debug(u, "Process of control group was killed by the OOM killer.");
+
+ /* This will probably need to be modified when scope units get an oom-policy */
+ switch (s->state) {
+
+ case SCOPE_START_CHOWN:
+ case SCOPE_RUNNING:
+ case SCOPE_STOP_SIGTERM:
+ scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_OOM_KILL);
+ break;
+
+ case SCOPE_STOP_SIGKILL:
+ if (s->result == SCOPE_SUCCESS)
+ s->result = SCOPE_FAILURE_OOM_KILL;
+ break;
+ /* SCOPE_DEAD, SCOPE_ABANDONED, and SCOPE_FAILED end up in default */
+ default:
+ ;
+ }
+}
+
static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
Scope *s = SCOPE(u);
[SCOPE_SUCCESS] = "success",
[SCOPE_FAILURE_RESOURCES] = "resources",
[SCOPE_FAILURE_TIMEOUT] = "timeout",
+ [SCOPE_FAILURE_OOM_KILL] = "oom-kill",
};
DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
.reset_failed = scope_reset_failed,
.notify_cgroup_empty = scope_notify_cgroup_empty_event,
+ .notify_cgroup_oom = scope_notify_cgroup_oom_event,
.bus_set_property = bus_scope_set_property,
.bus_commit_properties = bus_scope_commit_properties,
SCOPE_SUCCESS,
SCOPE_FAILURE_RESOURCES,
SCOPE_FAILURE_TIMEOUT,
+ SCOPE_FAILURE_OOM_KILL,
_SCOPE_RESULT_MAX,
_SCOPE_RESULT_INVALID = -EINVAL,
} ScopeResult;
unit_add_to_gc_queue(other);
+ /* The unit 'other' may not be wanted by the unit 'u'. */
+ unit_submit_to_stop_when_unneeded_queue(other);
+
done = false;
break;
}
#include "cryptsetup-util.h"
#include "env-util.h"
#include "escape.h"
+#include "fileio.h"
#include "libfido2-util.h"
#include "main-func.h"
#include "memory-util.h"
#include "tpm2-util.h"
static EnrollType arg_enroll_type = _ENROLL_TYPE_INVALID;
+static char *arg_unlock_keyfile = NULL;
static char *arg_pkcs11_token_uri = NULL;
static char *arg_fido2_device = NULL;
static char *arg_tpm2_device = NULL;
assert_cc(sizeof(arg_wipe_slots_mask) * 8 >= _ENROLL_TYPE_MAX);
+STATIC_DESTRUCTOR_REGISTER(arg_unlock_keyfile, freep);
STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_token_uri, freep);
STATIC_DESTRUCTOR_REGISTER(arg_fido2_device, freep);
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
STATIC_DESTRUCTOR_REGISTER(arg_node, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_wipe_slots, freep);
static bool wipe_requested(void) {
return arg_n_wipe_slots > 0 ||
" --version Show package version\n"
" --password Enroll a user-supplied password\n"
" --recovery-key Enroll a recovery key\n"
+ " --unlock-key-file=PATH\n"
+ " Use a file to unlock the volume\n"
" --pkcs11-token-uri=URI\n"
" Specify PKCS#11 security token URI\n"
" --fido2-credential-algorithm=STRING\n"
ARG_VERSION = 0x100,
ARG_PASSWORD,
ARG_RECOVERY_KEY,
+ ARG_UNLOCK_KEYFILE,
ARG_PKCS11_TOKEN_URI,
ARG_FIDO2_DEVICE,
ARG_TPM2_DEVICE,
{ "version", no_argument, NULL, ARG_VERSION },
{ "password", no_argument, NULL, ARG_PASSWORD },
{ "recovery-key", no_argument, NULL, ARG_RECOVERY_KEY },
+ { "unlock-key-file", required_argument, NULL, ARG_UNLOCK_KEYFILE },
{ "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI },
{ "fido2-credential-algorithm", required_argument, NULL, ARG_FIDO2_CRED_ALG },
{ "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE },
arg_enroll_type = ENROLL_RECOVERY;
break;
+ case ARG_UNLOCK_KEYFILE:
+ r = parse_path_argument(optarg, /* suppress_root= */ true, &arg_unlock_keyfile);
+ if (r < 0)
+ return r;
+ break;
+
case ARG_PKCS11_TOKEN_URI: {
_cleanup_free_ char *uri = NULL;
if (!vk)
return log_oom();
+ if (arg_unlock_keyfile) {
+ _cleanup_(erase_and_freep) char *password = NULL;
+ size_t password_len;
+
+ r = read_full_file_full(
+ AT_FDCWD,
+ arg_unlock_keyfile,
+ 0,
+ SIZE_MAX,
+ READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
+ NULL,
+ &password,
+ &password_len);
+ if (r < 0)
+ return log_error_errno(r, "Reading keyfile %s failed: %m", arg_unlock_keyfile);
+
+ r = crypt_volume_key_get(
+ cd,
+ CRYPT_ANY_SLOT,
+ vk,
+ &vks,
+ password,
+ password_len);
+ if (r < 0)
+ return log_error_errno(r, "Unlocking via keyfile failed: %m");
+
+ goto out;
+ }
+
r = getenv_steal_erase("PASSWORD", &envpw);
if (r < 0)
return log_error_errno(r, "Failed to acquire password from environment: %m");
}
}
+out:
*ret_cd = TAKE_PTR(cd);
*ret_volume_key = TAKE_PTR(vk);
*ret_volume_key_size = vks;
return log_error_errno(r, "Failed to read host timezone: %m");
(void) mkdir_parents(etc_localtime, 0755);
- if (symlink(p, etc_localtime) < 0)
- return log_error_errno(errno, "Failed to create %s symlink: %m", etc_localtime);
+ r = symlink_atomic(p, etc_localtime);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create %s symlink: %m", etc_localtime);
log_info("%s copied.", etc_localtime);
return 0;
e = strjoina("../usr/share/zoneinfo/", arg_timezone);
(void) mkdir_parents(etc_localtime, 0755);
- if (symlink(e, etc_localtime) < 0)
- return log_error_errno(errno, "Failed to create %s symlink: %m", etc_localtime);
+ r = symlink_atomic(e, etc_localtime);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create %s symlink: %m", etc_localtime);
log_info("%s written", etc_localtime);
return 0;
if (arg_root_password)
return 0;
- r = read_credential("passwd.hashed-password.root", (void**) &arg_root_password, NULL);
- if (r == -ENOENT) {
- r = read_credential("passwd.plaintext-password.root", (void**) &arg_root_password, NULL);
- if (r < 0)
- log_debug_errno(r, "Couldn't read credential 'passwd.{hashed|plaintext}-password.root', ignoring: %m");
- else {
- arg_root_password_is_hashed = false;
- return 0;
- }
- } else if (r < 0)
- log_debug_errno(r, "Couldn't read credential 'passwd.hashed-password.root', ignoring: %m");
- else {
- arg_root_password_is_hashed = true;
+ if (get_credential_user_password("root", &arg_root_password, &arg_root_password_is_hashed) >= 0)
return 0;
- }
if (!arg_prompt_root_password)
return 0;
dropin_dirname,
"Journal\0",
config_item_perf_lookup, journald_gperf_lookup,
- CONFIG_PARSE_WARN, s, NULL);
+ CONFIG_PARSE_WARN, s, NULL, NULL);
if (r < 0)
return r;
sd_bus_error_setfv;
sd_device_new_child;
+ sd_device_monitor_set_description;
+ sd_device_monitor_get_description;
sd_id128_string_equal;
if (!dir)
return -errno;
- log_debug("sd-device-enumerator: Scanning %s", path);
-
FOREACH_DIRENT_ALL(de, dir, return -errno) {
int k;
static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) {
int k, r = 0;
- log_debug("sd-device-enumerator: Scan all dirs");
-
k = enumerator_scan_dir(enumerator, "bus", "devices", NULL);
if (k < 0)
r = log_debug_errno(k, "sd-device-enumerator: Failed to scan /sys/bus: %m");
#include "string-util.h"
#include "strv.h"
+#define log_monitor(m, format, ...) \
+ log_debug("sd-device-monitor(%s): " format, strna(m ? m->description : NULL), ##__VA_ARGS__)
+#define log_monitor_errno(m, r, format, ...) \
+ log_debug_errno(r, "sd-device-monitor(%s): " format, strna(m ? m->description : NULL), ##__VA_ARGS__)
+#define log_device_monitor(d, m, format, ...) \
+ log_device_debug(d, "sd-device-monitor(%s): " format, strna(m ? m->description : NULL), ##__VA_ARGS__)
+#define log_device_monitor_errno(d, m, r, format, ...) \
+ log_device_debug_errno(d, r, "sd-device-monitor(%s): " format, strna(m ? m->description : NULL), ##__VA_ARGS__)
+
struct sd_device_monitor {
unsigned n_ref;
sd_event *event;
sd_event_source *event_source;
+ char *description;
sd_device_monitor_handler_t callback;
void *userdata;
};
* will not receive any messages.
*/
- log_debug("sd-device-monitor: The udev service seems not to be active, disabling the monitor");
+ log_monitor(m, "The udev service seems not to be active, disabling the monitor.");
group = MONITOR_GROUP_NONE;
}
if (fd < 0) {
sock = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT);
if (sock < 0)
- return log_debug_errno(errno, "sd-device-monitor: Failed to create socket: %m");
+ return log_monitor_errno(m, errno, "Failed to create socket: %m");
}
m = new(sd_device_monitor, 1);
if (fd >= 0) {
r = monitor_set_nl_address(m);
if (r < 0) {
- log_debug_errno(r, "sd-device-monitor: Failed to set netlink address: %m");
+ log_monitor_errno(m, r, "Failed to set netlink address: %m");
goto fail;
}
}
netns = ioctl(m->sock, SIOCGSKNS);
if (netns < 0)
- log_debug_errno(errno, "sd-device-monitor: Unable to get network namespace of udev netlink socket, unable to determine if we are in host netns, ignoring: %m");
+ log_monitor_errno(m, errno, "Unable to get network namespace of udev netlink socket, unable to determine if we are in host netns, ignoring: %m");
else {
struct stat a, b;
if (fstat(netns, &a) < 0) {
- r = log_debug_errno(errno, "sd-device-monitor: Failed to stat netns of udev netlink socket: %m");
+ r = log_monitor_errno(m, errno, "Failed to stat netns of udev netlink socket: %m");
goto fail;
}
if (ERRNO_IS_PRIVILEGE(errno))
/* If we can't access PID1's netns info due to permissions, it's fine, this is a
* safety check only after all. */
- log_debug_errno(errno, "sd-device-monitor: No permission to stat PID1's netns, unable to determine if we are in host netns, ignoring: %m");
+ log_monitor_errno(m, errno, "No permission to stat PID1's netns, unable to determine if we are in host netns, ignoring: %m");
else
- log_debug_errno(errno, "sd-device-monitor: Failed to stat PID1's netns, ignoring: %m");
+ log_monitor_errno(m, errno, "Failed to stat PID1's netns, ignoring: %m");
} else if (!stat_inode_same(&a, &b))
- log_debug("sd-device-monitor: Netlink socket we listen on is not from host netns, we won't see device events.");
+ log_monitor(m, "Netlink socket we listen on is not from host netns, we won't see device events.");
}
}
if (r < 0)
return r;
- (void) sd_event_source_set_description(m->event_source, "sd-device-monitor");
+ (void) sd_event_source_set_description(m->event_source, m->description ?: "sd-device-monitor");
return 0;
}
return m->event_source;
}
+_public_ int sd_device_monitor_set_description(sd_device_monitor *m, const char *description) {
+ int r;
+
+ assert_return(m, -EINVAL);
+
+ r = free_and_strdup(&m->description, description);
+ if (r <= 0)
+ return r;
+
+ if (m->event_source)
+ (void) sd_event_source_set_description(m->event_source, description);
+
+ return r;
+}
+
+_public_ int sd_device_monitor_get_description(sd_device_monitor *m, const char **ret) {
+ assert_return(m, -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ *ret = m->description;
+ return 0;
+}
+
int device_monitor_enable_receiving(sd_device_monitor *m) {
int r;
r = sd_device_monitor_filter_update(m);
if (r < 0)
- return log_debug_errno(r, "sd-device-monitor: Failed to update filter: %m");
+ return log_monitor_errno(m, r, "Failed to update filter: %m");
if (!m->bound) {
/* enable receiving of sender credentials */
r = setsockopt_int(m->sock, SOL_SOCKET, SO_PASSCRED, true);
if (r < 0)
- return log_debug_errno(r, "sd-device-monitor: Failed to set socket option SO_PASSCRED: %m");
+ return log_monitor_errno(m, r, "Failed to set socket option SO_PASSCRED: %m");
if (bind(m->sock, &m->snl.sa, sizeof(struct sockaddr_nl)) < 0)
- return log_debug_errno(errno, "sd-device-monitor: Failed to bind monitoring socket: %m");
+ return log_monitor_errno(m, errno, "Failed to bind monitoring socket: %m");
m->bound = true;
r = monitor_set_nl_address(m);
if (r < 0)
- return log_debug_errno(r, "sd-device-monitor: Failed to set address: %m");
+ return log_monitor_errno(m, r, "Failed to set address: %m");
}
return 0;
(void) sd_device_monitor_detach_event(m);
+ free(m->description);
hashmap_free(m->subsystem_filter);
set_free(m->tag_filter);
hashmap_free(m->match_sysattr_filter);
buflen = recvmsg(m->sock, &smsg, 0);
if (buflen < 0) {
- if (ERRNO_IS_TRANSIENT(errno))
- log_debug_errno(errno, "sd-device-monitor: Failed to receive message: %m");
+ if (!ERRNO_IS_TRANSIENT(errno))
+ log_monitor_errno(m, errno, "Failed to receive message: %m");
return -errno;
}
if (buflen < 32 || (smsg.msg_flags & MSG_TRUNC))
- return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
- "sd-device-monitor: Invalid message length.");
+ return log_monitor_errno(m, SYNTHETIC_ERRNO(EINVAL), "Invalid message length.");
if (snl.nl.nl_groups == MONITOR_GROUP_NONE) {
/* unicast message, check if we trust the sender */
if (m->snl_trusted_sender.nl.nl_pid == 0 ||
snl.nl.nl_pid != m->snl_trusted_sender.nl.nl_pid)
- return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
- "sd-device-monitor: Unicast netlink message ignored.");
+ return log_monitor_errno(m, SYNTHETIC_ERRNO(EAGAIN),
+ "Unicast netlink message ignored.");
} else if (snl.nl.nl_groups == MONITOR_GROUP_KERNEL) {
if (snl.nl.nl_pid > 0)
- return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
- "sd-device-monitor: Multicast kernel netlink message from PID %"PRIu32" ignored.", snl.nl.nl_pid);
+ return log_monitor_errno(m, SYNTHETIC_ERRNO(EAGAIN),
+ "Multicast kernel netlink message from PID %"PRIu32" ignored.",
+ snl.nl.nl_pid);
}
cmsg = CMSG_FIRSTHDR(&smsg);
if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS)
- return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
- "sd-device-monitor: No sender credentials received, message ignored.");
+ return log_monitor_errno(m, SYNTHETIC_ERRNO(EAGAIN),
+ "No sender credentials received, ignoring message.");
cred = (struct ucred*) CMSG_DATA(cmsg);
if (cred->uid != 0)
- return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
- "sd-device-monitor: Sender uid="UID_FMT", message ignored.", cred->uid);
+ return log_monitor_errno(m, SYNTHETIC_ERRNO(EAGAIN),
+ "Sender uid="UID_FMT", message ignored.", cred->uid);
if (streq(buf.raw, "libudev")) {
/* udev message needs proper version magic */
if (buf.nlh.magic != htobe32(UDEV_MONITOR_MAGIC))
- return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
- "sd-device-monitor: Invalid message signature (%x != %x)",
- buf.nlh.magic, htobe32(UDEV_MONITOR_MAGIC));
+ return log_monitor_errno(m, SYNTHETIC_ERRNO(EAGAIN),
+ "Invalid message signature (%x != %x).",
+ buf.nlh.magic, htobe32(UDEV_MONITOR_MAGIC));
if (buf.nlh.properties_off+32 > (size_t) buflen)
- return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
- "sd-device-monitor: Invalid message length (%u > %zd)",
- buf.nlh.properties_off+32, buflen);
+ return log_monitor_errno(m, SYNTHETIC_ERRNO(EAGAIN),
+ "Invalid message length (%u > %zd).",
+ buf.nlh.properties_off+32, buflen);
bufpos = buf.nlh.properties_off;
/* kernel message with header */
bufpos = strlen(buf.raw) + 1;
if ((size_t) bufpos < sizeof("a@/d") || bufpos >= buflen)
- return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
- "sd-device-monitor: Invalid message length");
+ return log_monitor_errno(m, SYNTHETIC_ERRNO(EAGAIN),
+ "Invalid message length.");
/* check message header */
if (!strstr(buf.raw, "@/"))
- return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
- "sd-device-monitor: Invalid message header");
+ return log_monitor_errno(m, SYNTHETIC_ERRNO(EAGAIN),
+ "Invalid message header.");
}
r = device_new_from_nulstr(&device, &buf.raw[bufpos], buflen - bufpos);
if (r < 0)
- return log_debug_errno(r, "sd-device-monitor: Failed to create device from received message: %m");
+ return log_monitor_errno(m, r, "Failed to create device from received message: %m");
if (is_initialized)
device_set_is_initialized(device);
/* Skip device, if it does not pass the current filter */
r = passes_filter(m, device);
if (r < 0)
- return log_device_debug_errno(device, r, "sd-device-monitor: Failed to check received device passing filter: %m");
+ return log_device_monitor_errno(device, m, r, "Failed to check received device passing filter: %m");
if (r == 0)
- log_device_debug(device, "sd-device-monitor: Received device does not pass filter, ignoring");
+ log_device_monitor(device, m, "Received device does not pass filter, ignoring.");
else
*ret = TAKE_PTR(device);
r = device_get_properties_nulstr(device, &buf, &blen);
if (r < 0)
- return log_device_debug_errno(device, r, "sd-device-monitor: Failed to get device properties: %m");
+ return log_device_monitor_errno(device, m, r, "Failed to get device properties: %m");
if (blen < 32)
- log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL),
- "sd-device-monitor: Length of device property nulstr is too small to contain valid device information");
+ return log_device_monitor_errno(device, m, SYNTHETIC_ERRNO(EINVAL),
+ "Length of device property nulstr is too small to contain valid device information.");
/* fill in versioned header */
r = sd_device_get_subsystem(device, &val);
if (r < 0)
- return log_device_debug_errno(device, r, "sd-device-monitor: Failed to get device subsystem: %m");
+ return log_device_monitor_errno(device, m, r, "Failed to get device subsystem: %m");
nlh.filter_subsystem_hash = htobe32(string_hash32(val));
if (sd_device_get_devtype(device, &val) >= 0)
count = sendmsg(m->sock, &smsg, 0);
if (count < 0) {
if (!destination && errno == ECONNREFUSED) {
- log_device_debug(device, "sd-device-monitor: Passed to netlink monitor");
+ log_device_monitor(device, m, "Passed to netlink monitor.");
return 0;
} else
- return log_device_debug_errno(device, errno, "sd-device-monitor: Failed to send device to netlink monitor: %m");
+ return log_device_monitor_errno(device, m, errno, "Failed to send device to netlink monitor: %m");
}
- log_device_debug(device, "sd-device-monitor: Passed %zi byte to netlink monitor", count);
+ log_device_monitor(device, m, "Passed %zi byte to netlink monitor.", count);
return count;
}
assert(device);
assert(_syspath);
- /* must be a subdirectory of /sys */
- if (!path_startswith(_syspath, "/sys/"))
- return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
- "sd-device: Syspath '%s' is not a subdirectory of /sys",
- _syspath);
-
if (verify) {
_cleanup_close_ int fd = -1;
+ /* The input path maybe a symlink located outside of /sys. Let's try to chase the symlink at first.
+ * The primary usecase is that e.g. /proc/device-tree is a symlink to /sys/firmware/devicetree/base.
+ * By chasing symlinks in the path at first, we can call sd_device_new_from_path() with such path. */
r = chase_symlinks(_syspath, NULL, 0, &syspath, &fd);
if (r == -ENOENT)
/* the device does not exist (any more?) */
"sd-device: the syspath \"%s\" is outside of sysfs, refusing.", syspath);
}
} else {
+ /* must be a subdirectory of /sys */
+ if (!path_startswith(_syspath, "/sys/"))
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "sd-device: Syspath '%s' is not a subdirectory of /sys",
+ _syspath);
+
syspath = strdup(_syspath);
if (!syspath)
return log_oom_debug();
return 0;
}
-_public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
+static int device_new_from_syspath(sd_device **ret, const char *syspath, bool strict) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
int r;
assert_return(ret, -EINVAL);
assert_return(syspath, -EINVAL);
+ if (strict && !path_startswith(syspath, "/sys/"))
+ return -EINVAL;
+
r = device_new_aux(&device);
if (r < 0)
return r;
return 0;
}
+_public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
+ return device_new_from_syspath(ret, syspath, /* strict = */ true);
+}
+
static int device_new_from_mode_and_devnum(sd_device **ret, mode_t mode, dev_t devnum) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
_cleanup_free_ char *syspath = NULL;
if (path_startswith(path, "/dev"))
return sd_device_new_from_devname(ret, path);
- return sd_device_new_from_syspath(ret, path);
+ return device_new_from_syspath(ret, path, /* strict = */ false);
}
int device_set_devtype(sd_device *device, const char *devtype) {
#include "device-private.h"
#include "device-util.h"
#include "macro.h"
+#include "path-util.h"
#include "stat-util.h"
#include "string-util.h"
#include "tests.h"
assert_se(sd_device_get_syspath(loopback, &syspath) >= 0);
assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0);
assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0);
assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
assert_se(device_monitor_send_device(monitor_server, monitor_client, loopback) >= 0);
assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0);
assert_se(sd_device_get_syspath(device, &syspath) >= 0);
assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0);
assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0);
assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
if (subsystem_filter) {
assert_se(sd_device_get_subsystem(device, &subsystem) >= 0);
assert_se(sd_device_get_subsystem(device, &subsystem) >= 0);
assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0);
assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0);
assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, NULL) >= 0);
assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_add_match_subsystem(e, subsystem, false) >= 0);
assert_se(sd_device_get_syspath(d, &p) >= 0);
assert_se(sd_device_get_subsystem(d, &s) >= 0);
+ assert_se(device_add_property(d, "ACTION", "add") >= 0);
+ assert_se(device_add_property(d, "SEQNUM", "10") >= 0);
+
log_device_debug(d, "Sending device subsystem:%s syspath:%s", s, p);
assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0);
}
assert_se(sd_device_get_syspath(device, &syspath) >= 0);
assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0);
assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0);
assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
assert_se(sd_device_monitor_filter_add_match_tag(monitor_client, "TEST_SD_DEVICE_MONITOR") >= 0);
assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
assert_se(sd_device_enumerator_new(&e) >= 0);
FOREACH_DEVICE(e, d) {
assert_se(sd_device_get_syspath(d, &p) >= 0);
+ assert_se(device_add_property(d, "ACTION", "add") >= 0);
+ assert_se(device_add_property(d, "SEQNUM", "10") >= 0);
+
log_device_debug(d, "Sending device syspath:%s", p);
assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0);
}
static void test_sysattr_filter(sd_device *device, const char *sysattr) {
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
- const char *syspath, *subsystem, *sysattr_value;
+ const char *syspath, *sysattr_value;
sd_device *d;
log_device_info(device, "/* %s(%s) */", __func__, sysattr);
assert_se(sd_device_get_syspath(device, &syspath) >= 0);
- assert_se(sd_device_get_subsystem(device, &subsystem) >= 0);
assert_se(sd_device_get_sysattr_value(device, sysattr, &sysattr_value) >= 0);
assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0);
assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0);
assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
- /* The sysattr filter is not implemented in BPF yet, so the below device_monito_send_device()
- * may cause EAGAIN. So, let's also filter devices with subsystem. */
- assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, NULL) >= 0);
assert_se(sd_device_monitor_filter_add_match_sysattr(monitor_client, sysattr, sysattr_value, true) >= 0);
assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_add_match_sysattr(e, sysattr, sysattr_value, false) >= 0);
assert_se(sd_device_get_syspath(d, &p) >= 0);
+ assert_se(device_add_property(d, "ACTION", "add") >= 0);
+ assert_se(device_add_property(d, "SEQNUM", "10") >= 0);
+
log_device_debug(d, "Sending device syspath:%s", p);
assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0);
+
+ /* The sysattr filter is not implemented in BPF yet. So, sending multiple devices may fills up
+ * buffer and device_monitor_send_device() may return EAGAIN. Let's send one device here,
+ * which should be filtered out by the receiver. */
+ break;
}
log_device_info(device, "Sending device syspath:%s", syspath);
static void test_parent_filter(sd_device *device) {
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
- const char *syspath, *subsystem;
+ const char *syspath, *parent_syspath;
sd_device *parent, *d;
int r;
log_device_info(device, "/* %s */", __func__);
assert_se(sd_device_get_syspath(device, &syspath) >= 0);
- assert_se(sd_device_get_subsystem(device, &subsystem) >= 0);
r = sd_device_get_parent(device, &parent);
if (r < 0)
return (void) log_device_info(device, "Device does not have parent, skipping.");
+ assert_se(sd_device_get_syspath(parent, &parent_syspath) >= 0);
assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0);
assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0);
assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
- /* The parent filter is not implemented in BPF yet, so the below device_monito_send_device()
- * may cause EAGAIN. So, let's also filter devices with subsystem. */
- assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, NULL) >= 0);
assert_se(sd_device_monitor_filter_add_match_parent(monitor_client, parent, true) >= 0);
assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
assert_se(sd_device_enumerator_new(&e) >= 0);
FOREACH_DEVICE(e, d) {
const char *p;
assert_se(sd_device_get_syspath(d, &p) >= 0);
+ if (path_startswith(p, parent_syspath))
+ continue;
+
+ assert_se(device_add_property(d, "ACTION", "add") >= 0);
+ assert_se(device_add_property(d, "SEQNUM", "10") >= 0);
log_device_debug(d, "Sending device syspath:%s", p);
assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0);
+
+ /* The parent filter is not implemented in BPF yet. So, sending multiple devices may fills up
+ * buffer and device_monitor_send_device() may return EAGAIN. Let's send one device here,
+ * which should be filtered out by the receiver. */
+ break;
}
log_device_info(device, "Sending device syspath:%s", syspath);
assert_se(sd_device_get_syspath(device, &syspath) >= 0);
assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_server, "sender") >= 0);
assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0);
assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0);
+ assert_se(sd_device_monitor_set_description(monitor_client, "receiver") >= 0);
assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0);
assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
- assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, "hoge", NULL) >= 0);
assert_se(sd_device_monitor_filter_update(monitor_client) >= 0);
#include <ctype.h>
#include <fcntl.h>
+#include <unistd.h>
#include "device-enumerator-private.h"
#include "device-internal.h"
#include "hashmap.h"
#include "nulstr-util.h"
#include "path-util.h"
+#include "rm-rf.h"
#include "string-util.h"
#include "tests.h"
#include "time-util.h"
+#include "tmpfile-util.h"
static void test_sd_device_one(sd_device *d) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
}
}
+TEST(sd_device_new_from_path) {
+ _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+ _cleanup_(rm_rf_physical_and_freep) char *tmpdir = NULL;
+ sd_device *dev;
+ int r;
+
+ assert_se(mkdtemp_malloc("/tmp/test-sd-device.XXXXXXX", &tmpdir) >= 0);
+
+ assert_se(sd_device_enumerator_new(&e) >= 0);
+ assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
+ assert_se(sd_device_enumerator_add_match_subsystem(e, "block", true) >= 0);
+ assert_se(sd_device_enumerator_add_nomatch_sysname(e, "loop*") >= 0);
+ assert_se(sd_device_enumerator_add_match_property(e, "DEVNAME", "*") >= 0);
+
+ FOREACH_DEVICE(e, dev) {
+ _cleanup_(sd_device_unrefp) sd_device *d = NULL;
+ const char *syspath, *devpath, *sysname, *s;
+ _cleanup_free_ char *path = NULL;
+
+ assert_se(sd_device_get_sysname(dev, &sysname) >= 0);
+
+ log_debug("%s(%s)", __func__, sysname);
+
+ assert_se(sd_device_get_syspath(dev, &syspath) >= 0);
+ assert_se(sd_device_new_from_path(&d, syspath) >= 0);
+ assert_se(sd_device_get_syspath(d, &s) >= 0);
+ assert_se(streq(s, syspath));
+ d = sd_device_unref(d);
+
+ assert_se(sd_device_get_devname(dev, &devpath) >= 0);
+ r = sd_device_new_from_path(&d, devpath);
+ if (r >= 0) {
+ assert_se(sd_device_get_syspath(d, &s) >= 0);
+ assert_se(streq(s, syspath));
+ d = sd_device_unref(d);
+ } else
+ assert_se(r == -ENODEV || ERRNO_IS_PRIVILEGE(r));
+
+ assert_se(path = path_join(tmpdir, sysname));
+ assert_se(symlink(syspath, path) >= 0);
+ assert_se(sd_device_new_from_path(&d, path) >= 0);
+ assert_se(sd_device_get_syspath(d, &s) >= 0);
+ assert_se(streq(s, syspath));
+ }
+}
+
DEFINE_TEST_MAIN(LOG_INFO);
static int append_session_cg_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit, const char *field) {
uint64_t val;
int r;
+ bool is_cpu_weight;
+ is_cpu_weight = streq(field, "CPUWeight");
if (isempty(limit))
return PAM_SUCCESS;
- r = cg_weight_parse(limit, &val);
+ r = is_cpu_weight ? cg_cpu_weight_parse(limit, &val) : cg_weight_parse(limit, &val);
if (r >= 0) {
r = sd_bus_message_append(m, "(sv)", field, "t", val);
if (r < 0)
return pam_bus_log_create_error(handle, r);
- } else if (streq(field, "CPUWeight"))
+ } else if (is_cpu_weight)
pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.cpu_weight, ignoring: %s", limit);
else
pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.io_weight, ignoring: %s", limit);
config_item_perf_lookup, network_netdev_gperf_lookup,
CONFIG_PARSE_WARN,
netdev_raw,
+ NULL,
NULL);
if (r < 0)
return r; /* config_parse_many() logs internally. */
NETDEV_VTABLE(netdev)->sections,
config_item_perf_lookup, network_netdev_gperf_lookup,
CONFIG_PARSE_WARN,
- netdev, NULL);
+ netdev, NULL, NULL);
if (r < 0)
return r; /* config_parse_many() logs internally. */
#include <linux/if_arp.h>
#include "bus-error.h"
+#include "bus-locator.h"
#include "dhcp-identifier.h"
#include "dhcp-internal.h"
#include "dhcp6-internal.h"
m->product_uuid_requested = false;
- r = sd_bus_call_method_async(
+ r = bus_call_method_async(
m->bus,
NULL,
- "org.freedesktop.hostname1",
- "/org/freedesktop/hostname1",
- "org.freedesktop.hostname1",
+ bus_hostname,
"GetProductUUID",
get_product_uuid_handler,
m,
return 0;
}
- r = sd_bus_call_method_async(
+ r = bus_call_method_async(
m->bus,
NULL,
- "org.freedesktop.hostname1",
- "/org/freedesktop/hostname1",
- "org.freedesktop.hostname1",
+ bus_hostname,
"SetHostname",
set_hostname_handler,
m,
config_item_perf_lookup, network_network_gperf_lookup,
CONFIG_PARSE_WARN,
network,
- &network->stats_by_path);
+ &network->stats_by_path,
+ NULL);
if (r < 0)
return r; /* config_parse_many() logs internally. */
return r;
if (link->network->use_bpdu >= 0) {
- r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, link->network->use_bpdu);
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu);
if (r < 0)
return r;
}
}
if (link->network->allow_port_to_be_root >= 0) {
- r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, link->network->allow_port_to_be_root);
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root);
if (r < 0)
return r;
}
assert(phys_port_ifindex > 0);
assert(virt_port_ifindex > 0);
- /* This sets ifindices only whenn both interfaces are already managed by us. */
+ /* This sets ifindices only when both interfaces are already managed by us. */
r = link_get_by_index(manager, phys_port_ifindex, &phys_link);
if (r < 0)
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return false;
- if (IN_SET(qdisc->parent, TC_H_ROOT, TC_H_CLSACT)) /* TC_H_CLSACT == TC_H_INGRESS */
- return true;
+ /* TC_H_CLSACT == TC_H_INGRESS */
+ if (!IN_SET(qdisc->parent, TC_H_ROOT, TC_H_CLSACT) &&
+ link_find_tclass(link, qdisc->parent, NULL) < 0)
+ return false;
+
+ if (QDISC_VTABLE(qdisc) &&
+ QDISC_VTABLE(qdisc)->is_ready &&
+ QDISC_VTABLE(qdisc)->is_ready(qdisc, link) <= 0)
+ return false;
- return link_find_tclass(link, qdisc->parent, NULL) >= 0;
+ return true;
}
static int qdisc_process_request(Request *req, Link *link, QDisc *qdisc) {
int (*init)(QDisc *qdisc);
int (*fill_message)(Link *link, QDisc *qdisc, sd_netlink_message *m);
int (*verify)(QDisc *qdisc);
+ int (*is_ready)(QDisc *qdisc, Link *link);
} QDiscVTable;
extern const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX];
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "macro.h"
+#include "networkd-link.h"
#include "parse-util.h"
#include "string-util.h"
#include "teql.h"
return free_and_replace(qdisc->tca_kind, tca_kind);
}
+static int trivial_link_equalizer_is_ready(QDisc *qdisc, Link *link) {
+ Link *teql;
+
+ assert(qdisc);
+ assert(qdisc->tca_kind);
+ assert(link);
+ assert(link->manager);
+
+ if (link_get_by_name(link->manager, qdisc->tca_kind, &teql) < 0)
+ return false;
+
+ return link_is_ready_to_configure(teql, /* allow_unmanaged = */ true);
+}
+
const QDiscVTable teql_vtable = {
.object_size = sizeof(TrivialLinkEqualizer),
.verify = trivial_link_equalizer_verify,
+ .is_ready = trivial_link_equalizer_is_ready,
};
int config_parse_trivial_link_equalizer_id(
SD_BUS_PARAM(fd),
bus_method_dump_by_fd,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_SIGNAL_WITH_NAMES("Killed",
+ "ss",
+ SD_BUS_PARAM(cgroup)
+ SD_BUS_PARAM(reason),
+ 0),
SD_BUS_VTABLE_END
};
r = cg_path_get_owner_uid(message.path, &cg_uid);
if (r < 0) {
- log_debug("Failed to get cgroup %s owner uid: %m", message.path);
+ log_debug_errno(r, "Failed to get cgroup %s owner uid: %m", message.path);
continue;
}
if (r < 0)
log_notice_errno(r, "Failed to kill any cgroup(s) based on swap: %m");
else {
- if (selected && r > 0)
+ if (selected && r > 0) {
log_notice("Killed %s due to memory used (%"PRIu64") / total (%"PRIu64") and "
"swap used (%"PRIu64") / total (%"PRIu64") being more than "
PERMYRIAD_AS_PERCENT_FORMAT_STR,
m->system_context.mem_used, m->system_context.mem_total,
m->system_context.swap_used, m->system_context.swap_total,
PERMYRIAD_AS_PERCENT_FORMAT_VAL(m->swap_used_limit_permyriad));
+
+ /* send dbus signal */
+ (void) sd_bus_emit_signal(m->bus,
+ "/org/freedesktop/oom1",
+ "org.freedesktop.oom1.Manager",
+ "Killed",
+ "ss",
+ selected,
+ "memory-used");
+ }
return 0;
}
}
* it. In either case, go through the event loop again and select a new candidate if
* pressure is still high. */
m->mem_pressure_post_action_delay_start = usec_now;
- if (selected && r > 0)
+ if (selected && r > 0) {
log_notice("Killed %s due to memory pressure for %s being %lu.%02lu%% > %lu.%02lu%%"
" for > %s with reclaim activity",
selected, t->path,
LOADAVG_INT_SIDE(t->memory_pressure.avg10), LOADAVG_DECIMAL_SIDE(t->memory_pressure.avg10),
LOADAVG_INT_SIDE(t->mem_pressure_limit), LOADAVG_DECIMAL_SIDE(t->mem_pressure_limit),
FORMAT_TIMESPAN(m->default_mem_pressure_duration_usec, USEC_PER_SEC));
+
+ /* send dbus signal */
+ (void) sd_bus_emit_signal(m->bus,
+ "/org/freedesktop/oom1",
+ "org.freedesktop.oom1.Manager",
+ "Killed",
+ "ss",
+ selected,
+ "memory-pressure");
+ }
return 0;
}
}
struct Partition {
char *definition_path;
+ char **drop_in_files;
sd_id128_t type_uuid;
sd_id128_t current_uuid, new_uuid;
free(p->current_label);
free(p->new_label);
free(p->definition_path);
+ strv_free(p->drop_in_files);
if (p->current_partition)
fdisk_unref_partition(p->current_partition);
return 0;
}
-static int partition_read_definition(Partition *p, const char *path) {
+static int partition_read_definition(Partition *p, const char *path, const char *const *conf_file_dirs) {
ConfigTableItem table[] = {
{ "Partition", "Type", config_parse_type, 0, &p->type_uuid },
{}
};
int r;
+ _cleanup_free_ char *filename = NULL;
+ const char* dropin_dirname;
- r = config_parse(NULL, path, NULL,
- "Partition\0",
- config_item_table_lookup, table,
- CONFIG_PARSE_WARN,
- p,
- NULL);
+ r = path_extract_filename(path, &filename);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extract filename from path '%s': %m", path);;
+
+ dropin_dirname = strjoina(filename, ".d");
+
+ r = config_parse_many(
+ STRV_MAKE_CONST(path),
+ conf_file_dirs,
+ dropin_dirname,
+ "Partition\0",
+ config_item_table_lookup, table,
+ CONFIG_PARSE_WARN,
+ p,
+ NULL,
+ &p->drop_in_files);
if (r < 0)
return r;
_cleanup_strv_free_ char **files = NULL;
Partition *last = NULL;
int r;
+ const char *const *dirs;
assert(context);
- if (directory)
- r = conf_files_list_strv(&files, ".conf", NULL, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char**) STRV_MAKE(directory));
- else
- r = conf_files_list_strv(&files, ".conf", root, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char**) CONF_PATHS_STRV("repart.d"));
+ dirs = directory ?
+ STRV_MAKE_CONST(directory) :
+ (const char* const*)CONF_PATHS_STRV("repart.d");
+
+ r = conf_files_list_strv(&files, ".conf", directory ? NULL : root, CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, dirs);
if (r < 0)
return log_error_errno(r, "Failed to enumerate *.conf files: %m");
if (!p->definition_path)
return log_oom();
- r = partition_read_definition(p, *f);
+ r = partition_read_definition(p, *f, dirs);
if (r < 0)
return r;
_cleanup_(table_unrefp) Table *t = NULL;
uint64_t sum_padding = 0, sum_size = 0;
int r;
+ const size_t dropin_files_col = 13;
+ bool no_dropin_files = true;
if ((arg_json_format_flags & JSON_FORMAT_OFF) && context->n_partitions == 0) {
log_info("Empty partition table.");
return 0;
}
- t = table_new("type", "label", "uuid", "file", "node", "offset", "old size", "raw size", "size", "old padding", "raw padding", "padding", "activity");
+ t = table_new("type", "label", "uuid", "file", "node", "offset", "old size", "raw size", "size", "old padding", "raw padding", "padding", "activity", "drop-in files");
if (!t)
return log_oom();
if (!DEBUG_LOGGING) {
if (arg_json_format_flags & JSON_FORMAT_OFF)
(void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4,
- (size_t) 8, (size_t) 11);
+ (size_t) 8, (size_t) 11, dropin_files_col);
else
(void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4,
- (size_t) 5, (size_t) 6, (size_t) 7, (size_t) 9, (size_t) 10, (size_t) 12);
+ (size_t) 5, (size_t) 6, (size_t) 7, (size_t) 9, (size_t) 10, (size_t) 12,
+ dropin_files_col);
}
(void) table_set_align_percent(t, table_get_cell(t, 0, 5), 100);
TABLE_UINT64, p->current_padding == UINT64_MAX ? 0 : p->current_padding,
TABLE_UINT64, p->new_padding,
TABLE_STRING, padding_change, TABLE_SET_COLOR, !p->partitions_next && sum_padding > 0 ? ansi_underline() : NULL,
- TABLE_STRING, activity ?: "unchanged");
+ TABLE_STRING, activity ?: "unchanged",
+ TABLE_STRV, p->drop_in_files);
if (r < 0)
return table_log_add_error(r);
+
+ no_dropin_files = no_dropin_files && strv_isempty(p->drop_in_files);
}
if ((arg_json_format_flags & JSON_FORMAT_OFF) && (sum_padding > 0 || sum_size > 0)) {
TABLE_EMPTY,
TABLE_EMPTY,
TABLE_STRING, b,
+ TABLE_EMPTY,
TABLE_EMPTY);
if (r < 0)
return table_log_add_error(r);
}
+ if (no_dropin_files) {
+ r = table_hide_column_from_display(t, dropin_files_col);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set columns to display: %m");
+ }
+
return table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
}
"$repart" "$D/zzz" --size=3G --dry-run=no --seed="$SEED" --definitions="$D/definitions" --no-pager --json=help
"$repart" "$D/zzz" --size=3G --dry-run=no --seed="$SEED" --definitions="$D/definitions" --no-pager --json=pretty
"$repart" "$D/zzz" --size=3G --dry-run=no --seed="$SEED" --definitions="$D/definitions" --no-pager --json=short
+
+echo "### Testing drop-in overrides ###"
+
+mkdir -p "$D/definitions-overrides"
+
+cat >"$D/definitions-overrides/root.conf" <<EOF
+[Partition]
+Type=swap
+SizeMaxBytes=64M
+UUID=837c3d67-21b3-478e-be82-7e7f83bf96d3
+EOF
+
+mkdir -p "$D/definitions-overrides/root.conf.d"
+
+cat >"$D/definitions-overrides/root.conf.d/override1.conf" <<EOF
+[Partition]
+Label=label1
+SizeMaxBytes=32M
+EOF
+
+cat >"$D/definitions-overrides/root.conf.d/override2.conf" <<EOF
+[Partition]
+Label=label2
+EOF
+
+rm -f test-drop-in-image
+
+JSON_OUTPUT=$("$repart" --definitions="$D/definitions-overrides" --dry-run=yes --empty=create --size=100M --json=pretty test-drop-in-image)
+
+diff <(echo "$JSON_OUTPUT") - <<EOF
+[
+ {
+ "type" : "swap",
+ "label" : "label2",
+ "uuid" : "837c3d67-21b3-478e-be82-7e7f83bf96d3",
+ "file" : "root.conf",
+ "node" : "test-drop-in-image1",
+ "offset" : 1048576,
+ "old_size" : 0,
+ "raw_size" : 33554432,
+ "old_padding" : 0,
+ "raw_padding" : 0,
+ "activity" : "create",
+ "drop-in_files" : [
+ "$D/definitions-overrides/root.conf.d/override1.conf",
+ "$D/definitions-overrides/root.conf.d/override2.conf"
+ ]
+ }
+]
+EOF
assert(s);
- dot = strchr(s, '.');
+ dot = strrchr(s, '.');
if (dot) {
_cleanup_free_ char *iface = NULL;
config_item_perf_lookup, resolved_dnssd_gperf_lookup,
CONFIG_PARSE_WARN,
service,
+ NULL,
NULL);
if (r < 0)
return r;
.interface = "org.freedesktop.timedate1"
};
+const BusLocator* const bus_hostname = &(BusLocator){
+ .destination = "org.freedesktop.hostname1",
+ .path = "/org/freedesktop/hostname1",
+ .interface = "org.freedesktop.hostname1"
+};
+
/* Shorthand flavors of the sd-bus convenience helpers with destination,path,interface strings encapsulated
* within a single struct. */
int bus_call_method_async(
extern const BusLocator* const bus_resolve_mgr;
extern const BusLocator* const bus_systemd_mgr;
extern const BusLocator* const bus_timedate;
+extern const BusLocator* const bus_hostname;
/* Shorthand flavors of the sd-bus convenience helpers with destination,path,interface strings encapsulated
* within a single struct. */
bus_print_property_value(name, expected_value, flags, s);
- } else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
+ } else if (STR_IN_SET(name, "CPUWeight", "StartupCPUWeight") && u == CGROUP_WEIGHT_IDLE)
+ bus_print_property_value(name, expected_value, flags, "idle");
+
+ else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
(STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
(STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) ||
(STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == UINT64_MAX) ||
DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_blkio_weight_parse);
DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_cpu_shares_parse);
DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_weight_parse);
+DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_cpu_weight_parse);
DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, unsigned long, mount_propagation_flags_from_string);
DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, safe_atou64);
DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, mode_t, parse_mode);
return bus_append_parse_boolean(m, field, eq);
if (STR_IN_SET(field, "CPUWeight",
- "StartupCPUWeight",
- "IOWeight",
+ "StartupCPUWeight"))
+ return bus_append_cg_cpu_weight_parse(m, field, eq);
+
+ if (STR_IN_SET(field, "IOWeight",
"StartupIOWeight"))
return bus_append_cg_weight_parse(m, field, eq);
return 0;
}
+int cg_cpu_weight_parse(const char *s, uint64_t *ret) {
+ if (streq_ptr(s, "idle"))
+ return *ret = CGROUP_WEIGHT_IDLE;
+ return cg_weight_parse(s, ret);
+}
+
int cg_cpu_shares_parse(const char *s, uint64_t *ret) {
uint64_t u;
int r;
bool cg_is_hybrid_wanted(void);
int cg_weight_parse(const char *s, uint64_t *ret);
+int cg_cpu_weight_parse(const char *s, uint64_t *ret);
int cg_cpu_shares_parse(const char *s, uint64_t *ret);
int cg_blkio_weight_parse(const char *s, uint64_t *ret);
const void *table,
ConfigParseFlags flags,
void *userdata,
- Hashmap **ret_stats_by_path) {
+ Hashmap **ret_stats_by_path,
+ char ***ret_dropin_files) {
_cleanup_strv_free_ char **files = NULL;
int r;
if (r < 0)
return r;
- return config_parse_many_files(conf_files, files, sections, lookup, table, flags, userdata, ret_stats_by_path);
+ r = config_parse_many_files(conf_files, files, sections, lookup, table, flags, userdata, ret_stats_by_path);
+ if (r < 0)
+ return r;
+
+ if (ret_dropin_files)
+ *ret_dropin_files = TAKE_PTR(files);
+
+ return 0;
}
static int dropins_get_stats_by_path(
const void *table,
ConfigParseFlags flags,
void *userdata,
- Hashmap **ret_stats_by_path); /* possibly NULL */
+ Hashmap **ret_stats_by_path, /* possibly NULL */
+ char ***ret_drop_in_files); /* possibly NULL */
int config_get_stats_by_path(
const char *suffix,
(char**) ret, ret_size);
}
+int get_credential_user_password(const char *username, char **ret_password, bool *ret_is_hashed) {
+ _cleanup_(erase_and_freep) char *creds_password = NULL;
+ _cleanup_free_ char *cn = NULL;
+ int r;
+
+ /* Try to pick up the password for this account via the credentials logic */
+ cn = strjoin("passwd.hashed-password.", username);
+ if (!cn)
+ return -ENOMEM;
+
+ r = read_credential(cn, (void**) &creds_password, NULL);
+ if (r == -ENOENT) {
+ free(cn);
+ cn = strjoin("passwd.plaintext-password.", username);
+ if (!cn)
+ return -ENOMEM;
+
+ r = read_credential(cn, (void**) &creds_password, NULL);
+ if (r < 0)
+ log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
+ else
+ *ret_is_hashed = false;
+ } else if (r < 0)
+ log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
+ else
+ *ret_is_hashed = true;
+
+ *ret_password = TAKE_PTR(creds_password);
+
+ return r;
+}
+
#if HAVE_OPENSSL
#define CREDENTIAL_HOST_SECRET_SIZE 4096
int get_credential_host_secret(CredentialSecretFlags flags, void **ret, size_t *ret_size);
+int get_credential_user_password(const char *username, char **ret_password, bool *ret_is_hashed);
+
/* The four modes we support: keyed only by on-disk key, only by TPM2 HMAC key, and by the combination of
* both, as well as one with a fixed zero length key if TPM2 is missing (the latter of course provides no
* authenticity or confidentiality, but is still useful for integrity protection, and makes things simpler
{ "v249", NAMING_V249 },
{ "v250", NAMING_V250 },
{ "v251", NAMING_V251 },
+ { "v252", NAMING_V252 },
/* … add more schemes here, as the logic to name devices is updated … */
EXTRA_NET_NAMING_MAP
NAMING_REPLACE_STRICTLY = 1 << 12, /* Use udev_replace_ifname() for NAME= rule */
NAMING_XEN_VIF = 1 << 13, /* Generate names for Xen netfront devices */
NAMING_BRIDGE_MULTIFUNCTION_SLOT = 1 << 14, /* Use PCI hotplug slot information associated with bridge, but only if PCI device is multifunction */
+ NAMING_DEVICETREE_ALIASES = 1 << 15, /* Generate names from devicetree aliases */
/* And now the masks that combine the features above */
NAMING_V238 = 0,
NAMING_V249 = NAMING_V247 | NAMING_SLOT_FUNCTION_ID | NAMING_16BIT_INDEX | NAMING_REPLACE_STRICTLY,
NAMING_V250 = NAMING_V249 | NAMING_XEN_VIF,
NAMING_V251 = NAMING_V250 | NAMING_BRIDGE_MULTIFUNCTION_SLOT,
+ NAMING_V252 = NAMING_V251 | NAMING_DEVICETREE_ALIASES,
EXTRA_NET_NAMING_SCHEMES
#include <syslog.h>
#include <unistd.h>
+#include "sd-device.h"
+
#include "alloc-util.h"
#include "blockdev-util.h"
#include "btrfs-util.h"
#include "conf-parser.h"
#include "def.h"
+#include "device-util.h"
#include "devnum-util.h"
#include "env-util.h"
#include "errno-util.h"
#include "strv.h"
#include "time-util.h"
+#define BATTERY_LOW_CAPACITY_LEVEL 5
#define DISCHARGE_RATE_FILEPATH "/var/lib/systemd/sleep/battery_discharge_percentage_rate_per_hour"
#define BATTERY_DISCHARGE_RATE_HASH_KEY SD_ID128_MAKE(5f,9a,20,18,38,76,46,07,8d,36,58,0b,bb,c4,e0,63)
+static void *CAPACITY_TO_PTR(int capacity) {
+ assert(capacity >= 0);
+ assert(capacity <= 100);
+ return INT_TO_PTR(capacity + 1);
+}
+
+static int PTR_TO_CAPACITY(void *p) {
+ int capacity = PTR_TO_INT(p) - 1;
+ assert(capacity >= 0);
+ assert(capacity <= 100);
+ return capacity;
+}
+
int parse_sleep_config(SleepConfig **ret_sleep_config) {
_cleanup_(free_sleep_configp) SleepConfig *sc = NULL;
int allow_suspend = -1, allow_hibernate = -1,
return 0;
}
-/* If battery percentage capacity is less than equal to 5% return success */
-int battery_is_low(void) {
+/* Get the list of batteries */
+static int battery_enumerator_new(sd_device_enumerator **ret) {
+ _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
int r;
- /* We have not used battery capacity_level since value is set to full
- * or Normal in case acpi is not working properly. In case of no battery
- * 0 will be returned and system will be suspended for 1st cycle then hibernated */
+ assert(ret);
- r = read_battery_capacity_percentage();
- if (r == -ENOENT)
- return false;
+ r = sd_device_enumerator_new(&e);
+ if (r < 0)
+ return r;
+
+ r = sd_device_enumerator_add_match_subsystem(e, "power_supply", /* match= */ true);
+ if (r < 0)
+ return r;
+
+ r = sd_device_enumerator_add_match_property(e, "POWER_SUPPLY_TYPE", "Battery");
if (r < 0)
- return r;
+ return r;
+
+ *ret = TAKE_PTR(e);
- return r <= 5;
+ return 0;
+}
+
+static int get_capacity_by_name(Hashmap *capacities_by_name, const char *name) {
+ void *p;
+
+ assert(capacities_by_name);
+ assert(name);
+
+ p = hashmap_get(capacities_by_name, name);
+ if (!p)
+ return -ENOENT;
+
+ return PTR_TO_CAPACITY(p);
}
/* Battery percentage capacity fetched from capacity file and if in range 0-100 then returned */
-int read_battery_capacity_percentage(void) {
- _cleanup_free_ char *bat_cap = NULL;
+static int read_battery_capacity_percentage(sd_device *dev) {
+ const char *power_supply_capacity;
int battery_capacity, r;
- r = read_one_line_file("/sys/class/power_supply/BAT0/capacity", &bat_cap);
- if (r == -ENOENT)
- return log_debug_errno(r, "/sys/class/power_supply/BAT0/capacity is unavailable. Assuming no battery exists: %m");
+ assert(dev);
+
+ r = sd_device_get_property_value(dev, "POWER_SUPPLY_CAPACITY", &power_supply_capacity);
if (r < 0)
- return log_debug_errno(r, "Failed to read /sys/class/power_supply/BAT0/capacity: %m");
+ return log_device_debug_errno(dev, r, "Failed to read battery capacity: %m");
- r = safe_atoi(bat_cap, &battery_capacity);
+ r = safe_atoi(power_supply_capacity, &battery_capacity);
if (r < 0)
- return log_debug_errno(r, "Failed to parse battery capacity: %m");
+ return log_device_debug_errno(dev, r, "Failed to parse battery capacity: %m");
if (battery_capacity < 0 || battery_capacity > 100)
- return log_debug_errno(SYNTHETIC_ERRNO(ERANGE), "Invalid battery capacity");
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ERANGE), "Invalid battery capacity");
return battery_capacity;
}
-/* Read file path and return hash of value in that file */
-static int get_battery_identifier(const char *filepath, struct siphash *ret) {
- _cleanup_free_ char *value = NULL;
+/* If battery percentage capacity is less than equal to 5% return success */
+int battery_is_low(void) {
+ _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+ sd_device *dev;
+ int r;
+
+ /* We have not used battery capacity_level since value is set to full
+ * or Normal in case acpi is not working properly. In case of no battery
+ * 0 will be returned and system will be suspended for 1st cycle then hibernated */
+
+ r = battery_enumerator_new(&e);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
+
+ FOREACH_DEVICE(e, dev) {
+ r = read_battery_capacity_percentage(dev);
+ if (r < 0) {
+ log_device_debug_errno(dev, r, "Failed to get battery capacity, ignoring: %m");
+ continue;
+ }
+ if (r > BATTERY_LOW_CAPACITY_LEVEL)
+ return false;
+ }
+
+ return true;
+}
+
+/* Store current capacity of each battery before suspension and timestamp */
+int fetch_batteries_capacity_by_name(Hashmap **ret) {
+ _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+ _cleanup_(hashmap_freep) Hashmap *batteries_capacity_by_name = NULL;
+ sd_device *dev;
int r;
- assert(filepath);
assert(ret);
- r = read_one_line_file(filepath, &value);
+ batteries_capacity_by_name = hashmap_new(&string_hash_ops_free);
+ if (!batteries_capacity_by_name)
+ return log_oom_debug();
+
+ r = battery_enumerator_new(&e);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
+
+ FOREACH_DEVICE(e, dev) {
+ _cleanup_free_ char *battery_name_copy = NULL;
+ const char *battery_name;
+ int battery_capacity;
+
+ battery_capacity = r = read_battery_capacity_percentage(dev);
+ if (r < 0) {
+ log_device_debug_errno(dev, r, "Failed to get battery capacity, ignoring: %m");
+ continue;
+ }
+
+ r = sd_device_get_property_value(dev, "POWER_SUPPLY_NAME", &battery_name);
+ if (r < 0) {
+ log_device_debug_errno(dev, r, "Failed to read battery name, ignoring: %m");
+ continue;
+ }
+
+ battery_name_copy = strdup(battery_name);
+ if (!battery_name_copy)
+ return log_oom_debug();
+
+ r = hashmap_put(batteries_capacity_by_name, battery_name_copy, CAPACITY_TO_PTR(battery_capacity));
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to store battery capacity: %m");
+
+ TAKE_PTR(battery_name_copy);
+ }
+
+ *ret = TAKE_PTR(batteries_capacity_by_name);
+
+ return 0;
+}
+
+/* Read file path and return hash of value in that file */
+static int get_battery_identifier(sd_device *dev, const char *property, struct siphash *state) {
+ const char *x;
+ int r;
+
+ assert(dev);
+ assert(property);
+ assert(state);
+
+ r = sd_device_get_property_value(dev, property, &x);
if (r == -ENOENT)
- log_debug_errno(r, "%s is unavailable: %m", filepath);
+ log_device_debug_errno(dev, r, "battery device property %s is unavailable, ignoring: %m", property);
else if (r < 0)
- return log_debug_errno(r, "Failed to read %s: %m", filepath);
- else if (isempty(value))
- log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "%s is empty: %m", filepath);
+ return log_device_debug_errno(dev, r, "Failed to read battery device property %s: %m", property);
+ else if (isempty(x))
+ log_device_debug(dev, "battery device property '%s' is null.", property);
else
- siphash24_compress_string(value, ret);
+ siphash24_compress_string(x, state);
return 0;
}
/* Read system and battery identifier from specific location and generate hash of it */
-static int get_system_battery_identifier_hash(uint64_t *ret_hash) {
+static int get_system_battery_identifier_hash(sd_device *dev, uint64_t *ret) {
struct siphash state;
sd_id128_t machine_id, product_id;
int r;
- assert(ret_hash);
+ assert(ret);
+ assert(dev);
siphash24_init(&state, BATTERY_DISCHARGE_RATE_HASH_KEY.bytes);
- get_battery_identifier("/sys/class/power_supply/BAT0/manufacturer", &state);
- get_battery_identifier("/sys/class/power_supply/BAT0/model_name", &state);
- get_battery_identifier("/sys/class/power_supply/BAT0/serial_number", &state);
+
+ get_battery_identifier(dev, "POWER_SUPPLY_MANUFACTURER", &state);
+ get_battery_identifier(dev, "POWER_SUPPLY_MODEL_NAME", &state);
+ get_battery_identifier(dev, "POWER_SUPPLY_SERIAL_NUMBER", &state);
r = sd_id128_get_machine(&machine_id);
if (r == -ENOENT)
else
siphash24_compress(&product_id, sizeof(sd_id128_t), &state);
- *ret_hash = siphash24_finalize(&state);
+ *ret = siphash24_finalize(&state);
return 0;
}
/* Battery percentage discharge rate per hour is read from specific file. It is stored along with system
* and battery identifier hash to maintain the integrity of discharge rate value */
-int get_battery_discharge_rate(void) {
- _cleanup_free_ char *hash_id_discharge_rate = NULL, *stored_hash_id = NULL, *stored_discharge_rate = NULL;
+static int get_battery_discharge_rate(sd_device *dev, int *ret) {
+ _cleanup_fclose_ FILE *f = NULL;
+ uint64_t current_hash_id;
const char *p;
- uint64_t current_hash_id, hash_id;
- int discharge_rate, r;
+ int r;
- r = read_one_line_file(DISCHARGE_RATE_FILEPATH, &hash_id_discharge_rate);
- if (r < 0)
- return log_debug_errno(r, "Failed to read discharge rate from %s: %m", DISCHARGE_RATE_FILEPATH);
+ assert(dev);
+ assert(ret);
- p = hash_id_discharge_rate;
- r = extract_many_words(&p, " ", 0, &stored_hash_id, &stored_discharge_rate, NULL);
- if (r < 0)
- return log_debug_errno(r, "Failed to parse hash_id and discharge_rate read from %s location: %m", DISCHARGE_RATE_FILEPATH);
- if (r != 2)
- return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid number of items fetched from %s", DISCHARGE_RATE_FILEPATH);
+ f = fopen(DISCHARGE_RATE_FILEPATH, "re");
+ if (!f)
+ return log_debug_errno(errno, "Failed to read discharge rate from " DISCHARGE_RATE_FILEPATH ": %m");
- r = safe_atou64(stored_hash_id, &hash_id);
+ r = get_system_battery_identifier_hash(dev, ¤t_hash_id);
if (r < 0)
- return log_debug_errno(r, "Failed to parse discharge rate read from %s location: %m", DISCHARGE_RATE_FILEPATH);
+ return log_device_debug_errno(dev, r, "Failed to generate system battery identifier hash: %m");
- r = get_system_battery_identifier_hash(¤t_hash_id);
- if (r < 0)
- return log_debug_errno(r, "Failed to generate system battery identifier hash: %m");
+ for (;;) {
+ _cleanup_free_ char *stored_hash_id = NULL, *stored_discharge_rate = NULL, *line = NULL;
+ uint64_t hash_id;
+ int discharge_rate;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to read discharge rate from " DISCHARGE_RATE_FILEPATH ": %m");
+ if (r == 0)
+ break;
- if(current_hash_id != hash_id)
- return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Current identifier does not match stored identifier: %m");
+ p = line;
+ r = extract_many_words(&p, NULL, 0, &stored_hash_id, &stored_discharge_rate, NULL);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to parse hash_id and discharge_rate read from " DISCHARGE_RATE_FILEPATH ": %m");
+ if (r != 2)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid number of items fetched from " DISCHARGE_RATE_FILEPATH);
- r = safe_atoi(stored_discharge_rate, &discharge_rate);
- if (r < 0)
- return log_debug_errno(r, "Failed to parse discharge rate read from %s location: %m", DISCHARGE_RATE_FILEPATH);
+ r = safe_atou64(stored_hash_id, &hash_id);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to parse hash ID read from " DISCHARGE_RATE_FILEPATH " location: %m");
+
+ if (current_hash_id != hash_id)
+ /* matching device not found, move to next line */
+ continue;
+
+ r = safe_atoi(stored_discharge_rate, &discharge_rate);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to parse discharge rate read from " DISCHARGE_RATE_FILEPATH ": %m");
+
+ if (!battery_discharge_rate_is_valid(discharge_rate))
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ERANGE), "Invalid battery discharge percentage rate per hour: %m");
- if (!battery_discharge_rate_is_valid(discharge_rate))
- return log_debug_errno(SYNTHETIC_ERRNO(ERANGE), "Invalid battery discharge percentage rate per hour: %m");
+ *ret = discharge_rate;
+ return 0; /* matching device found, exit iteration */
+ }
- return discharge_rate;
+ return -ENOENT;
}
/* Write battery percentage discharge rate per hour along with system and battery identifier hash to file */
-int put_battery_discharge_rate(int estimated_battery_discharge_rate) {
- uint64_t system_hash_id;
+static int put_battery_discharge_rate(int estimated_battery_discharge_rate, uint64_t system_hash_id, bool trunc) {
int r;
if (!battery_discharge_rate_is_valid(estimated_battery_discharge_rate))
- return log_debug_errno(SYNTHETIC_ERRNO(ERANGE), "Invalid battery discharge percentage rate per hour: %m");
+ return log_debug_errno(SYNTHETIC_ERRNO(ERANGE),
+ "Invalid battery discharge rate %d%% per hour: %m",
+ estimated_battery_discharge_rate);
- r = get_system_battery_identifier_hash(&system_hash_id);
+ r = write_string_filef(
+ DISCHARGE_RATE_FILEPATH,
+ WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_MKDIR_0755 | (trunc ? WRITE_STRING_FILE_TRUNCATE : 0),
+ "%"PRIu64" %d",
+ system_hash_id,
+ estimated_battery_discharge_rate);
if (r < 0)
- return log_debug_errno(r, "Failed to generate system battery identifier hash: %m");
+ return log_debug_errno(r, "Failed to update %s: %m", DISCHARGE_RATE_FILEPATH);
- r = write_string_filef(
- DISCHARGE_RATE_FILEPATH,
- WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755,
- "%"PRIu64" %d",
- system_hash_id,
- estimated_battery_discharge_rate);
+ log_debug("Estimated discharge rate %d%% per hour successfully saved to %s", estimated_battery_discharge_rate, DISCHARGE_RATE_FILEPATH);
+
+ return 0;
+}
+
+/* Estimate battery discharge rate using stored previous and current capacity over timestamp difference */
+int estimate_battery_discharge_rate_per_hour(
+ Hashmap *last_capacity,
+ Hashmap *current_capacity,
+ usec_t before_timestamp,
+ usec_t after_timestamp) {
+
+ _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+ sd_device *dev;
+ bool trunc = true;
+ int r;
+
+ assert(last_capacity);
+ assert(current_capacity);
+ assert(before_timestamp < after_timestamp);
+
+ r = battery_enumerator_new(&e);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
+
+ FOREACH_DEVICE(e, dev) {
+ int battery_last_capacity, battery_current_capacity, battery_discharge_rate;
+ const char *battery_name;
+ uint64_t system_hash_id;
+
+ r = sd_device_get_property_value(dev, "POWER_SUPPLY_NAME", &battery_name);
+ if (r < 0) {
+ log_device_debug_errno(dev, r, "Failed to read battery name, ignoring: %m");
+ continue;
+ }
+
+ battery_last_capacity = get_capacity_by_name(last_capacity, battery_name);
+ if (battery_last_capacity < 0)
+ continue;
+
+ battery_current_capacity = get_capacity_by_name(current_capacity, battery_name);
+ if (battery_current_capacity < 0)
+ continue;
+
+ if (battery_current_capacity >= battery_last_capacity) {
+ log_device_debug(dev, "Battery was not discharged during suspension");
+ continue;
+ }
+
+ r = get_system_battery_identifier_hash(dev, &system_hash_id);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to generate system battery identifier hash: %m");
+
+ log_device_debug(dev,
+ "%d%% was discharged in %s. Estimating discharge rate...",
+ battery_last_capacity - battery_current_capacity,
+ FORMAT_TIMESPAN(after_timestamp - before_timestamp, USEC_PER_SEC));
+
+ battery_discharge_rate = (battery_last_capacity - battery_current_capacity) * USEC_PER_HOUR / (after_timestamp - before_timestamp);
+ r = put_battery_discharge_rate(battery_discharge_rate, system_hash_id, trunc);
+ if (r < 0)
+ log_device_warning_errno(dev, r, "Failed to update battery discharge rate, ignoring: %m");
+ else
+ trunc = false;
+ }
+
+ return 0;
+}
+
+/* calculate the suspend interval for each battery and then return the sum of it */
+int get_total_suspend_interval(Hashmap *last_capacity, usec_t *ret) {
+ _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+ usec_t total_suspend_interval = 0;
+ sd_device *dev;
+ int r;
+
+ assert(last_capacity);
+ assert(ret);
+
+ r = battery_enumerator_new(&e);
if (r < 0)
- return log_debug_errno(r, "Failed to create %s: %m", DISCHARGE_RATE_FILEPATH);
+ return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
+
+ FOREACH_DEVICE(e, dev) {
+ int battery_last_capacity, previous_discharge_rate = 0;
+ const char *battery_name;
+ usec_t suspend_interval;
+
+ r = sd_device_get_property_value(dev, "POWER_SUPPLY_NAME", &battery_name);
+ if (r < 0) {
+ log_device_debug_errno(dev, r, "Failed to read battery name, ignoring: %m");
+ continue;
+ }
+
+ battery_last_capacity = PTR_TO_CAPACITY(hashmap_get(last_capacity, battery_name));
+ if (battery_last_capacity <= 0)
+ continue;
+
+ r = get_battery_discharge_rate(dev, &previous_discharge_rate);
+ if (r < 0) {
+ log_device_debug_errno(dev, r, "Failed to get discharge rate, ignoring: %m");
+ continue;
+ }
+
+ if (previous_discharge_rate == 0)
+ continue;
+
+ if (battery_last_capacity * 2 <= previous_discharge_rate) {
+ log_device_debug(dev, "Current battery capacity percentage too low compared to discharge rate");
+ continue;
+ }
+ suspend_interval = battery_last_capacity * USEC_PER_HOUR / previous_discharge_rate;
+
+ total_suspend_interval = usec_add(total_suspend_interval, suspend_interval);
+ }
+ /* The previous discharge rate is stored in per hour basis so converted to minutes.
+ * Subtracted 30 minutes from the result to keep a buffer of 30 minutes before battery gets critical */
+ total_suspend_interval = usec_sub_unsigned(total_suspend_interval, 30 * USEC_PER_MINUTE);
+ if (total_suspend_interval == 0)
+ return -ENOENT;
+
+ *ret = total_suspend_interval;
- log_debug("Estimated discharge rate %d successfully updated to %s", estimated_battery_discharge_rate, DISCHARGE_RATE_FILEPATH);
return 0;
}
#pragma once
#include <linux/fiemap.h>
+
+#include "hashmap.h"
#include "time-util.h"
typedef enum SleepOperation {
int can_sleep(SleepOperation operation);
int can_sleep_disk(char **types);
int can_sleep_state(char **types);
-int read_battery_capacity_percentage(void);
int battery_is_low(void);
-int get_battery_discharge_rate(void);
-int put_battery_discharge_rate(int estimated_battery_discharge_rate);
+int get_total_suspend_interval(Hashmap *last_capacity, usec_t *ret);
+int fetch_batteries_capacity_by_name(Hashmap **ret_current_capacity);
+int estimate_battery_discharge_rate_per_hour(
+ Hashmap *last_capacity,
+ Hashmap *current_capacity,
+ usec_t before_timestamp,
+ usec_t after_timestamp);
const char* sleep_operation_to_string(SleepOperation s) _const_;
SleepOperation sleep_operation_from_string(const char *s) _pure_;
.type = TPM2_ALG_ECC,
.nameAlg = TPM2_ALG_SHA256,
.objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
- .parameters = {
- .eccDetail = {
- .symmetric = {
- .algorithm = TPM2_ALG_AES,
- .keyBits.aes = 128,
- .mode.aes = TPM2_ALG_CFB,
- },
- .scheme.scheme = TPM2_ALG_NULL,
- .curveID = TPM2_ECC_NIST_P256,
- .kdf.scheme = TPM2_ALG_NULL,
+ .parameters.eccDetail = {
+ .symmetric = {
+ .algorithm = TPM2_ALG_AES,
+ .keyBits.aes = 128,
+ .mode.aes = TPM2_ALG_CFB,
},
+ .scheme.scheme = TPM2_ALG_NULL,
+ .curveID = TPM2_ECC_NIST_P256,
+ .kdf.scheme = TPM2_ALG_NULL,
},
},
};
.type = TPM2_ALG_RSA,
.nameAlg = TPM2_ALG_SHA256,
.objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
- .parameters = {
- .rsaDetail = {
- .symmetric = {
- .algorithm = TPM2_ALG_AES,
- .keyBits.aes = 128,
- .mode.aes = TPM2_ALG_CFB,
- },
- .scheme.scheme = TPM2_ALG_NULL,
- .keyBits = 2048,
+ .parameters.rsaDetail = {
+ .symmetric = {
+ .algorithm = TPM2_ALG_AES,
+ .keyBits.aes = 128,
+ .mode.aes = TPM2_ALG_CFB,
},
+ .scheme.scheme = TPM2_ALG_NULL,
+ .keyBits = 2048,
},
},
};
static int tpm2_make_encryption_session(
ESYS_CONTEXT *c,
- ESYS_TR tpmKey,
+ ESYS_TR primary,
ESYS_TR *ret_session) {
static const TPMT_SYM_DEF symmetric = {
* recover the salt, which is then used for key derivation. */
rc = sym_Esys_StartAuthSession(
c,
- tpmKey,
+ primary,
ESYS_TR_NONE,
ESYS_TR_NONE,
ESYS_TR_NONE,
static int tpm2_make_pcr_session(
ESYS_CONTEXT *c,
- ESYS_TR tpmKey,
+ ESYS_TR primary,
ESYS_TR parent_session,
uint32_t pcr_mask,
uint16_t pcr_bank, /* If UINT16_MAX, pick best bank automatically, otherwise specify bank explicitly. */
static const TPMT_SYM_DEF symmetric = {
.algorithm = TPM2_ALG_AES,
- .keyBits = {
- .aes = 128
- },
- .mode = {
- .aes = TPM2_ALG_CFB,
- }
+ .keyBits.aes = 128,
+ .mode.aes = TPM2_ALG_CFB,
};
_cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
TPML_PCR_SELECTION pcr_selection;
rc = sym_Esys_StartAuthSession(
c,
- tpmKey,
+ primary,
ESYS_TR_NONE,
parent_session,
ESYS_TR_NONE,
.type = TPM2_ALG_KEYEDHASH,
.nameAlg = TPM2_ALG_SHA256,
.objectAttributes = TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT,
- .parameters = {
- .keyedHashDetail = {
- .scheme.scheme = TPM2_ALG_NULL,
- },
- },
- .unique = {
- .keyedHash = {
- .size = 32,
- },
- },
+ .parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL,
+ .unique.keyedHash.size = 32,
.authPolicy = *policy_digest,
},
};
if (hr->memory_max != UINT64_MAX)
printf(" Memory Max: %s\n", FORMAT_BYTES(hr->memory_max));
- if (hr->cpu_weight != UINT64_MAX)
+ if (hr->cpu_weight == CGROUP_WEIGHT_IDLE)
+ printf(" CPU Weight: %s\n", "idle");
+ else if (hr->cpu_weight != UINT64_MAX)
printf(" CPU Weight: %" PRIu64 "\n", hr->cpu_weight);
if (hr->io_weight != UINT64_MAX)
}
static int execute_s2h(const SleepConfig *sleep_config) {
+ _cleanup_hashmap_free_ Hashmap *last_capacity = NULL, *current_capacity = NULL;
int r;
assert(sleep_config);
while (battery_is_low() == 0) {
_cleanup_close_ int tfd = -1;
struct itimerspec ts = {};
- usec_t suspend_interval = sleep_config->hibernate_delay_sec, before_timestamp = 0, after_timestamp = 0;
+ usec_t suspend_interval = sleep_config->hibernate_delay_sec, before_timestamp = 0, after_timestamp = 0, total_suspend_interval;
bool woken_by_timer;
- int last_capacity = 0, current_capacity = 0, previous_discharge_rate, estimated_discharge_rate = 0;
tfd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK|TFD_CLOEXEC);
if (tfd < 0)
return log_error_errno(errno, "Error creating timerfd: %m");
/* Store current battery capacity and current time before suspension */
- r = read_battery_capacity_percentage();
- if (r >= 0) {
- last_capacity = r;
- log_debug("Current battery charge percentage: %d%%", last_capacity);
+ r = fetch_batteries_capacity_by_name(&last_capacity);
+ if (r >= 0)
before_timestamp = now(CLOCK_BOOTTIME);
- } else if (r == -ENOENT)
+ else if (r == -ENOENT)
/* In case of no battery, system suspend interval will be set to HibernateDelaySec=. */
log_debug_errno(r, "Suspend Interval value set to %s: %m", FORMAT_TIMESPAN(suspend_interval, USEC_PER_SEC));
else
return log_error_errno(r, "Error fetching battery capacity percentage: %m");
- r = get_battery_discharge_rate();
+ r = get_total_suspend_interval(last_capacity, &total_suspend_interval);
if (r < 0)
- log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, "Failed to get discharge rate, ignoring: %m");
- else if (last_capacity * 2 <= r) {
- /* System should hibernate in case discharge rate is higher than double of battery current capacity
- * why double : Because while calculating suspend interval, we have taken a buffer of 30 minute and
- * discharge_rate is calculated on per 60 minute basis which is double. Also suspend_interval > 0 */
- log_debug("Current battery percentage capacity too low to suspend, so invoking hibernation");
- break;
- } else {
- previous_discharge_rate = r;
- assert(previous_discharge_rate != 0);
- suspend_interval = usec_sub_unsigned(last_capacity * USEC_PER_HOUR / previous_discharge_rate, 30 * USEC_PER_MINUTE);
- /* The previous discharge rate is stored in per hour basis so converted to minutes.
- * Subtracted 30 minutes from the result to keep a buffer of 30 minutes before battery gets critical */
- }
+ log_debug_errno(r, "Failed to estimate suspend interval using previous discharge rate, ignoring: %m");
+ else
+ suspend_interval = total_suspend_interval;
+
log_debug("Set timerfd wake alarm for %s", FORMAT_TIMESPAN(suspend_interval, USEC_PER_SEC));
/* Wake alarm for system with or without battery to hibernate or estimate discharge rate whichever is applicable */
timespec_store(&ts.it_value, suspend_interval);
/* Store fd_wait status */
woken_by_timer = FLAGS_SET(r, POLLIN);
- r = read_battery_capacity_percentage();
- if (r >= 0) {
- current_capacity = r;
- log_debug("Current battery charge percentage after wakeup: %d%%", current_capacity);
- } else if (r == -ENOENT) {
- /* In case of no battery, system will be hibernated after 1st cycle of suspend */
+ r = fetch_batteries_capacity_by_name(¤t_capacity);
+ if (r < 0) {
+ /* In case of no battery or error while getting charge level, no need to measure
+ * discharge rate. Instead system should wakeup if it is manual wakeup or
+ * hibernate if this is a timer wakeup. */
log_debug_errno(r, "Battery capacity percentage unavailable, cannot estimate discharge rate: %m");
+ if (!woken_by_timer)
+ return 0;
break;
- } else
- return log_error_errno(r, "Error fetching battery capacity percentage: %m");
+ }
- if (current_capacity >= last_capacity)
- log_debug("Battery was not discharged during suspension");
- else {
- after_timestamp = now(CLOCK_BOOTTIME);
- log_debug("Attempting to estimate battery discharge rate after wakeup from %s sleep", FORMAT_TIMESPAN(after_timestamp - before_timestamp, USEC_PER_HOUR));
+ after_timestamp = now(CLOCK_BOOTTIME);
+ log_debug("Attempting to estimate battery discharge rate after wakeup from %s sleep", FORMAT_TIMESPAN(after_timestamp - before_timestamp, USEC_PER_HOUR));
- estimated_discharge_rate = (last_capacity - current_capacity) * USEC_PER_HOUR / (after_timestamp - before_timestamp);
- r = put_battery_discharge_rate(estimated_discharge_rate);
+ if (after_timestamp != before_timestamp) {
+ r = estimate_battery_discharge_rate_per_hour(last_capacity, current_capacity, before_timestamp, after_timestamp);
if (r < 0)
- log_warning_errno(r, "Failed to update battery discharge rate, ignoring: %m");
- }
+ log_warning_errno(r, "Failed to estimate and update battery discharge rate, ignoring: %m");
+ } else
+ log_debug("System woke up too early to estimate discharge rate");
if (!woken_by_timer)
/* Return as manual wakeup done. This also will return in case battery was charged during suspension */
int sd_device_monitor_detach_event(sd_device_monitor *m);
sd_event *sd_device_monitor_get_event(sd_device_monitor *m);
sd_event_source *sd_device_monitor_get_event_source(sd_device_monitor *m);
+int sd_device_monitor_set_description(sd_device_monitor *m, const char *description);
+int sd_device_monitor_get_description(sd_device_monitor *m, const char **ret);
int sd_device_monitor_start(sd_device_monitor *m, sd_device_monitor_handler_t callback, void *userdata);
int sd_device_monitor_stop(sd_device_monitor *m);
ORDERED_HASHMAP_FOREACH(i, todo_uids) {
_cleanup_(erase_and_freep) char *creds_password = NULL;
- _cleanup_free_ char *cn = NULL;
+ bool is_hashed;
struct spwd n = {
.sp_namp = i->name,
.sp_flag = ULONG_MAX, /* this appears to be what everybody does ... */
};
- /* Try to pick up the password for this account via the credentials logic */
- cn = strjoin("passwd.hashed-password.", i->name);
- if (!cn)
- return -ENOMEM;
-
- r = read_credential(cn, (void**) &creds_password, NULL);
- if (r == -ENOENT) {
- _cleanup_(erase_and_freep) char *plaintext_password = NULL;
-
- free(cn);
- cn = strjoin("passwd.plaintext-password.", i->name);
- if (!cn)
- return -ENOMEM;
+ r = get_credential_user_password(i->name, &creds_password, &is_hashed);
+ if (r < 0)
+ log_debug_errno(r, "Couldn't read password credential for user '%s', ignoring: %m", i->name);
- r = read_credential(cn, (void**) &plaintext_password, NULL);
+ if (creds_password && !is_hashed) {
+ _cleanup_(erase_and_freep) char* plaintext_password = TAKE_PTR(creds_password);
+ r = hash_password(plaintext_password, &creds_password);
if (r < 0)
- log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
- else {
- r = hash_password(plaintext_password, &creds_password);
- if (r < 0)
- return log_debug_errno(r, "Failed to hash password: %m");
- }
- } else if (r < 0)
- log_debug_errno(r, "Couldn't read credential '%s', ignoring: %m", cn);
+ return log_debug_errno(r, "Failed to hash password: %m");
+ }
if (creds_password)
n.sp_pwdp = creds_password;
/* Take care to not iterate beyond the last valid track as specified in
* the TOC, but also avoid going beyond the TOC length, just in case
* the last track number is invalidly large */
- for (size_t i = 4; i + 8 < len && num_tracks > 0; i += 8, --num_tracks) {
+ for (size_t i = 4; i + 8 <= len && num_tracks > 0; i += 8, --num_tracks) {
bool is_data_track;
uint32_t block;
"Link\0"
"SR-IOV\0",
config_item_perf_lookup, link_config_gperf_lookup,
- CONFIG_PARSE_WARN, config, &stats_by_path);
+ CONFIG_PARSE_WARN, config, &stats_by_path,
+ NULL);
if (r < 0)
return r; /* config_parse_many() logs internally. */
#include <linux/pci_regs.h>
#include "alloc-util.h"
+#include "chase-symlinks.h"
#include "device-util.h"
#include "dirent-util.h"
#include "fd-util.h"
NET_XENVIF,
NET_PLATFORM,
NET_NETDEVSIM,
+ NET_DEVICETREE,
} NetNameType;
typedef struct NetNames {
char xen_slot[ALTIFNAMSIZ];
char platform_path[ALTIFNAMSIZ];
char netdevsim_path[ALTIFNAMSIZ];
+ char devicetree_onboard[ALTIFNAMSIZ];
} NetNames;
/* skip intermediate virtio devices */
return 0;
}
+static int dev_devicetree_onboard(sd_device *dev, NetNames *names) {
+ _cleanup_(sd_device_unrefp) sd_device *aliases_dev = NULL, *ofnode_dev = NULL, *devicetree_dev = NULL;
+ const char *alias, *ofnode_path, *ofnode_syspath, *devicetree_syspath;
+ sd_device *parent;
+ int r;
+
+ if (!naming_scheme_has(NAMING_DEVICETREE_ALIASES))
+ return 0;
+
+ /* check if our direct parent has an of_node */
+ r = sd_device_get_parent(dev, &parent);
+ if (r < 0)
+ return r;
+
+ r = sd_device_new_child(&ofnode_dev, parent, "of_node");
+ if (r < 0)
+ return r;
+
+ r = sd_device_get_syspath(ofnode_dev, &ofnode_syspath);
+ if (r < 0)
+ return r;
+
+ /* /proc/device-tree should be a symlink to /sys/firmware/devicetree/base. */
+ r = sd_device_new_from_path(&devicetree_dev, "/proc/device-tree");
+ if (r < 0)
+ return r;
+
+ r = sd_device_get_syspath(devicetree_dev, &devicetree_syspath);
+ if (r < 0)
+ return r;
+
+ /*
+ * Example paths:
+ * devicetree_syspath = /sys/firmware/devicetree/base
+ * ofnode_syspath = /sys/firmware/devicetree/base/soc/ethernet@deadbeef
+ * ofnode_path = soc/ethernet@deadbeef
+ */
+ ofnode_path = path_startswith(ofnode_syspath, devicetree_syspath);
+ if (!ofnode_path)
+ return -ENOENT;
+
+ /* Get back our leading / to match the contents of the aliases */
+ ofnode_path--;
+ assert(path_is_absolute(ofnode_path));
+
+ r = sd_device_new_child(&aliases_dev, devicetree_dev, "aliases");
+ if (r < 0)
+ return r;
+
+ FOREACH_DEVICE_SYSATTR(aliases_dev, alias) {
+ const char *alias_path, *alias_index, *conflict;
+ unsigned i;
+
+ alias_index = startswith(alias, "ethernet");
+ if (!alias_index)
+ continue;
+
+ if (sd_device_get_sysattr_value(aliases_dev, alias, &alias_path) < 0)
+ continue;
+
+ if (!path_equal(ofnode_path, alias_path))
+ continue;
+
+ /* If there's no index, we default to 0... */
+ if (isempty(alias_index)) {
+ i = 0;
+ conflict = "ethernet0";
+ } else {
+ r = safe_atou(alias_index, &i);
+ if (r < 0)
+ return log_device_debug_errno(dev, r,
+ "Could not get index of alias %s: %m", alias);
+ conflict = "ethernet";
+ }
+
+ /* ...but make sure we don't have an alias conflict */
+ if (i == 0 && sd_device_get_sysattr_value(aliases_dev, conflict, NULL) >= 0)
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST),
+ "Ethernet alias conflict: ethernet and ethernet0 both exist");
+
+ xsprintf(names->devicetree_onboard, "d%u", i);
+ names->type = NET_DEVICETREE;
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
static int names_pci(sd_device *dev, const LinkInfo *info, NetNames *names) {
_cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL;
_cleanup_free_ char *virtfn_suffix = NULL;
ieee_oui(dev, &info, test);
}
+ /* get devicetree aliases; only ethernet supported for now */
+ if (streq(prefix, "en") && dev_devicetree_onboard(dev, &names) >= 0 &&
+ names.type == NET_DEVICETREE) {
+ char str[ALTIFNAMSIZ];
+
+ if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.devicetree_onboard))
+ udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str);
+ }
+
/* get path names for Linux on System z network devices */
if (names_ccw(dev, &names) >= 0 && names.type == NET_CCW) {
char str[ALTIFNAMSIZ];
if (r < 0)
return r;
+ (void) sd_device_monitor_set_description(worker_monitor, "worker");
+
/* allow the main daemon netlink address to send devices to the worker */
r = device_monitor_allow_unicast_sender(worker_monitor, manager->monitor);
if (r < 0)
log_warning_errno(r, "Failed to set receive buffer size for device monitor, ignoring: %m");
}
+ (void) sd_device_monitor_set_description(manager->monitor, "manager");
+
r = device_monitor_enable_receiving(manager->monitor);
if (r < 0)
return log_error_errno(r, "Failed to bind netlink socket: %m");
self.assertEqual(self.read_attr('port2', 'brport/path_cost'), '555')
self.assertEqual(self.read_attr('port2', 'brport/multicast_fast_leave'), '1')
self.assertEqual(self.read_attr('port2', 'brport/unicast_flood'), '1')
- self.assertEqual(self.read_attr('port2', 'brport/bpdu_guard'), '1')
- self.assertEqual(self.read_attr('port2', 'brport/root_block'), '1')
+ self.assertEqual(self.read_attr('port2', 'brport/bpdu_guard'), '0')
+ self.assertEqual(self.read_attr('port2', 'brport/root_block'), '0')
class ClientTestBase(NetworkdTestingUtilities):
"""Provide common methods for testing networkd against servers."""
+++ /dev/null
-# SPDX-License-Identifier: LGPL-2.1-or-later
-[Match]
-Name=dummy98
-
-[Network]
-IPv6AcceptRA=no
-Address=10.1.2.3/16
-
-[QDisc]
-Parent=clsact
-
-[HierarchyTokenBucket]
-Parent=root
-Handle=0002
-DefaultClass=30
-RateToQuantum=20
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:0030
-Priority=1
-QuantumBytes=4000
-MTUBytes=1700
-OverheadBytes=100
-Rate=1M
-BufferBytes=123456
-CeilRate=0.5M
-CeilBufferBytes=123457
-
-[NetworkEmulator]
-Parent=2:30
-Handle=0030
-DelaySec=50ms
-DelayJitterSec=10ms
-LossRate=20%
-PacketLimit=100
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:0031
-Priority=1
-Rate=1M
-CeilRate=0.5M
-
-[TrivialLinkEqualizer]
-Parent=2:31
-Handle=0031
-Id=1
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:0032
-Priority=1
-Rate=1M
-CeilRate=0.5M
-
-[FairQueueing]
-Parent=2:32
-Handle=0032
-PacketLimit=1000
-FlowLimit=200
-QuantumBytes=1500
-InitialQuantumBytes=13000
-MaximumRate=1M
-Buckets=512
-OrphanMask=511
-Pacing=yes
-CEThresholdSec=100ms
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:0033
-Priority=1
-Rate=1M
-CeilRate=0.5M
-
-[ControlledDelay]
-Parent=2:33
-Handle=0033
-PacketLimit=2000
-TargetSec=10ms
-IntervalSec=50ms
-ECN=yes
-CEThresholdSec=100ms
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:0034
-Priority=1
-Rate=1M
-CeilRate=0.5M
-
-[FairQueueingControlledDelay]
-Parent=2:34
-Handle=0034
-PacketLimit=20480
-MemoryLimitBytes=64M
-Flows=2048
-TargetSec=10ms
-IntervalSec=200ms
-QuantumBytes=1400
-ECN=yes
-CEThresholdSec=100ms
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:0035
-Priority=1
-Rate=1M
-CeilRate=0.5M
-
-[TokenBucketFilter]
-Parent=2:35
-Handle=0035
-Rate=1G
-BurstBytes=5000
-LatencySec=70msec
-PeakRate=100G
-MTUBytes=1000000
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:0036
-Priority=1
-Rate=1M
-CeilRate=0.5M
-
-[StochasticFairnessQueueing]
-Parent=2:36
-Handle=0036
-PerturbPeriodSec=5sec
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:0037
-Priority=1
-Rate=1M
-CeilRate=0.5M
-
-[PFIFO]
-Parent=2:37
-Handle=0037
-PacketLimit=100000
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:0038
-Priority=1
-Rate=1M
-CeilRate=0.5M
-
-[GenericRandomEarlyDetection]
-Parent=2:38
-Handle=0038
-VirtualQueues=12
-DefaultVirtualQueue=10
-GenericRIO=yes
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:0039
-Priority=1
-Rate=1M
-CeilRate=0.5M
-
-[StochasticFairBlue]
-Parent=2:39
-Handle=0039
-PacketLimit=200000
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:003a
-Priority=1
-Rate=1M
-CeilRate=0.5M
-
-[BFIFO]
-Parent=2:3a
-Handle=003a
-LimitBytes=1000000
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:003b
-Priority=1
-Rate=1M
-CeilRate=0.5M
-
-[PFIFOHeadDrop]
-Parent=2:3b
-Handle=003b
-PacketLimit=1023
-
-[HierarchyTokenBucketClass]
-Parent=root
-ClassId=0002:003c
-Priority=1
-Rate=1M
-CeilRate=0.5M
-
-[PFIFOFast]
-Parent=2:3c
-Handle=003c
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.3/16
+
+[QDisc]
+Parent=clsact
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.3/16
+
+[ControlledDelay]
+Parent=root
+Handle=0033
+PacketLimit=2000
+TargetSec=10ms
+IntervalSec=50ms
+ECN=yes
+CEThresholdSec=100ms
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.3/16
+
+[FairQueueing]
+Parent=root
+Handle=0032
+PacketLimit=1000
+FlowLimit=200
+QuantumBytes=1500
+InitialQuantumBytes=13000
+MaximumRate=1M
+Buckets=512
+OrphanMask=511
+Pacing=yes
+CEThresholdSec=100ms
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.3/16
+
+[FairQueueingControlledDelay]
+Parent=root
+Handle=0034
+PacketLimit=20480
+MemoryLimitBytes=64M
+Flows=2048
+TargetSec=10ms
+IntervalSec=200ms
+QuantumBytes=1400
+ECN=yes
+CEThresholdSec=100ms
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.3/16
+
+[GenericRandomEarlyDetection]
+Parent=root
+Handle=0038
+VirtualQueues=12
+DefaultVirtualQueue=10
+GenericRIO=yes
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.3/16
+
+[HierarchyTokenBucket]
+Parent=root
+Handle=0002
+DefaultClass=30
+RateToQuantum=20
+
+[HierarchyTokenBucketClass]
+Parent=root
+ClassId=0002:0037
+Priority=1
+Rate=1M
+CeilRate=0.5M
+QuantumBytes=4000
+MTUBytes=1700
+OverheadBytes=100
+BufferBytes=123456
+CeilBufferBytes=123457
+
+[PFIFO]
+Parent=2:37
+Handle=0037
+PacketLimit=100000
+
+[HierarchyTokenBucketClass]
+Parent=root
+ClassId=0002:003a
+Priority=1
+Rate=1M
+CeilRate=0.5M
+
+[BFIFO]
+Parent=2:3a
+Handle=003a
+LimitBytes=1000000
+
+[HierarchyTokenBucketClass]
+Parent=root
+ClassId=0002:003b
+Priority=1
+Rate=1M
+CeilRate=0.5M
+
+[PFIFOHeadDrop]
+Parent=2:3b
+Handle=003b
+PacketLimit=1023
+
+[HierarchyTokenBucketClass]
+Parent=root
+ClassId=0002:003c
+Priority=1
+Rate=1M
+CeilRate=0.5M
+
+[PFIFOFast]
+Parent=2:3c
+Handle=003c
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=test1
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.4/16
+
+[QDisc]
+Parent=ingress
NetworkEmulatorDelayJitterSec=10ms
NetworkEmulatorLossRate=20%
NetworkEmulatorPacketLimit=100
-
-[TrafficControlQueueingDiscipline]
-Parent=ingress
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.3/16
+
+[NetworkEmulator]
+Parent=root
+Handle=0030
+DelaySec=50ms
+DelayJitterSec=10ms
+LossRate=20%
+PacketLimit=100
# SPDX-License-Identifier: LGPL-2.1-or-later
[Match]
-Name=test1
+Name=dummy98
[Network]
IPv6AcceptRA=no
-Address=10.1.2.4/16
+Address=10.1.2.3/16
[QuickFairQueueing]
Parent=root
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.3/16
+
+[StochasticFairBlue]
+Parent=root
+Handle=0039
+PacketLimit=200000
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.3/16
+
+[StochasticFairnessQueueing]
+Parent=root
+Handle=0036
+PerturbPeriodSec=5sec
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.3/16
+
+[TokenBucketFilter]
+Parent=root
+Handle=0035
+Rate=1G
+BurstBytes=5000
+LatencySec=70msec
+PeakRate=100G
+MTUBytes=1000000
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=dummy98
+
+[Network]
+IPv6AcceptRA=no
+Address=10.1.2.3/16
+
+[TrivialLinkEqualizer]
+Parent=root
+Handle=0031
+Id=1
# SPDX-License-Identifier: LGPL-2.1-or-later
[NetDev]
-Name=tap99
+Name=testtap99
Kind=tap
[Tap]
# SPDX-License-Identifier: LGPL-2.1-or-later
[NetDev]
-Name=tun99
+Name=testtun99
Kind=tun
[Tun]
networkd_bin = shutil.which('systemd-networkd', path=which_paths)
resolved_bin = shutil.which('systemd-resolved', path=which_paths)
+timesyncd_bin = shutil.which('systemd-timesyncd', path=which_paths)
udevd_bin = shutil.which('systemd-udevd', path=which_paths)
wait_online_bin = shutil.which('systemd-networkd-wait-online', path=which_paths)
networkctl_bin = shutil.which('networkctl', path=which_paths)
resolvectl_bin = shutil.which('resolvectl', path=which_paths)
timedatectl_bin = shutil.which('timedatectl', path=which_paths)
+udevadm_bin = shutil.which('udevadm', path=which_paths)
use_valgrind = False
+valgrind_cmd = ''
enable_debug = True
env = {}
wait_online_env = {}
def touch(path):
pathlib.Path(path).touch()
-def check_output(*command, text=True, **kwargs):
+def check_output(*command, **kwargs):
# This checks the result and returns stdout (and stderr) on success.
command = command[0].split() + list(command[1:])
- return subprocess.run(command, check=True, universal_newlines=text, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs).stdout.rstrip()
-
-def call(*command, text=True, **kwargs):
+ ret = subprocess.run(command, check=False, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs)
+ if ret.returncode == 0:
+ return ret.stdout.rstrip()
+ # When returncode != 0, print stdout and stderr, then trigger CalledProcessError.
+ print(ret.stdout)
+ ret.check_returncode()
+
+def call(*command, **kwargs):
# This returns returncode. stdout and stderr are merged and shown in console
command = command[0].split() + list(command[1:])
- return subprocess.run(command, check=False, universal_newlines=text, stderr=subprocess.STDOUT, **kwargs).returncode
+ return subprocess.run(command, check=False, universal_newlines=True, stderr=subprocess.STDOUT, **kwargs).returncode
-def call_quiet(*command, text=True, **kwargs):
+def call_quiet(*command, **kwargs):
command = command[0].split() + list(command[1:])
- return subprocess.run(command, check=False, universal_newlines=text, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, **kwargs).returncode
+ return subprocess.run(command, check=False, universal_newlines=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, **kwargs).returncode
-def run(*command, text=True, **kwargs):
+def run(*command, **kwargs):
# This returns CompletedProcess instance.
command = command[0].split() + list(command[1:])
- return subprocess.run(command, check=False, universal_newlines=text, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
+ return subprocess.run(command, check=False, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
def is_module_available(module_name):
lsmod_output = check_output('lsmod')
return f
-def expectedFailureIfCAKEIsNotAvailable():
- def f(func):
- call_quiet('ip link add dummy98 type dummy')
- rc = call_quiet('tc qdisc add dev dummy98 parent root cake')
- remove_link('dummy98')
- return func if rc == 0 else unittest.expectedFailure(func)
-
- return f
-
-def expectedFailureIfPIEIsNotAvailable():
- def f(func):
- call_quiet('ip link add dummy98 type dummy')
- rc = call_quiet('tc qdisc add dev dummy98 parent root pie')
- remove_link('dummy98')
- return func if rc == 0 else unittest.expectedFailure(func)
-
- return f
-
-def expectedFailureIfHHFIsNotAvailable():
- def f(func):
- call_quiet('ip link add dummy98 type dummy')
- rc = call_quiet('tc qdisc add dev dummy98 parent root hhf')
- remove_link('dummy98')
- return func if rc == 0 else unittest.expectedFailure(func)
-
- return f
-
-def expectedFailureIfETSIsNotAvailable():
- def f(func):
- call_quiet('ip link add dummy98 type dummy')
- rc = call_quiet('tc qdisc add dev dummy98 parent root ets bands 10')
- remove_link('dummy98')
- return func if rc == 0 else unittest.expectedFailure(func)
-
- return f
-
-def expectedFailureIfFQPIEIsNotAvailable():
- def f(func):
- call_quiet('ip link add dummy98 type dummy')
- rc = call_quiet('tc qdisc add dev dummy98 parent root fq_pie')
- remove_link('dummy98')
- return func if rc == 0 else unittest.expectedFailure(func)
-
- return f
-
def udev_reload():
- check_output('udevadm control --reload')
+ check_output(*udevadm_cmd, 'control', '--reload')
def copy_network_unit(*units, copy_dropins=True):
"""
def save_active_units():
for u in ['systemd-networkd.socket', 'systemd-networkd.service',
- 'systemd-resolved.service',
+ 'systemd-resolved.service', 'systemd-timesyncd.service',
'firewalld.service']:
if call(f'systemctl is-active --quiet {u}') == 0:
call(f'systemctl stop {u}')
for u in active_units:
call(f'systemctl restart {u}')
+def create_unit_dropin(unit, contents):
+ mkdir_p(f'/run/systemd/system/{unit}.d')
+ with open(f'/run/systemd/system/{unit}.d/00-override.conf', mode='w', encoding='utf-8') as f:
+ f.write('\n'.join(contents))
+
+def create_service_dropin(service, command, reload_command=None, additional_settings=None):
+ drop_in = [
+ '[Service]',
+ 'ExecStart=',
+ f'ExecStart=!!{valgrind_cmd}{command}',
+ ]
+ if reload_command:
+ drop_in += [
+ 'ExecReload=',
+ f'ExecReload={valgrind_cmd}{reload_command}',
+ ]
+ if enable_debug:
+ drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
+ if asan_options:
+ drop_in += [f'Environment=ASAN_OPTIONS="{asan_options}"']
+ if lsan_options:
+ drop_in += [f'Environment=LSAN_OPTIONS="{lsan_options}"']
+ if ubsan_options:
+ drop_in += [f'Environment=UBSAN_OPTIONS="{ubsan_options}"']
+ if asan_options or lsan_options or ubsan_options:
+ drop_in += ['SystemCallFilter=']
+ if use_valgrind or asan_options or lsan_options or ubsan_options:
+ drop_in += ['MemoryDenyWriteExecute=no']
+ if use_valgrind:
+ drop_in += [
+ 'Environment=SYSTEMD_MEMPOOL=0',
+ 'PrivateTmp=yes',
+ ]
+ if with_coverage:
+ drop_in += [
+ 'ProtectSystem=no',
+ 'ProtectHome=no',
+ ]
+ if additional_settings:
+ drop_in += additional_settings
+
+ create_unit_dropin(f'{service}.service', drop_in)
+
def link_exists(link):
return os.path.exists(os.path.join('/sys/class/net', link, 'ifindex'))
def save_timezone():
global saved_timezone
- r = run('timedatectl show --value --property Timezone')
+ r = run(*timedatectl_cmd, 'show', '--value', '--property', 'Timezone', env=env)
if r.returncode == 0:
saved_timezone = r.stdout.rstrip()
print(f'### Saved timezone: {saved_timezone}')
def restore_timezone():
if saved_timezone:
- call(f'timedatectl set-timezone {saved_timezone}')
+ call(*timedatectl_cmd, 'set-timezone', f'{saved_timezone}', env=env)
def read_link_attr(*args):
with open(os.path.join('/sys/class/net', *args), encoding='utf-8') as f:
check_output('systemctl start systemd-networkd')
def restart_networkd(show_logs=True):
- stop_networkd(show_logs)
- start_networkd()
+ if show_logs:
+ invocation_id = check_output('systemctl show systemd-networkd.service -p InvocationID --value')
+ check_output('systemctl restart systemd-networkd.service')
+ if show_logs:
+ print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id))
def networkctl_reconfigure(*links):
check_output(*networkctl_cmd, 'reconfigure', *links, env=env)
save_routing_policy_rules()
save_timezone()
- drop_in = [
- '[Unit]',
- 'StartLimitIntervalSec=0',
- '[Service]',
- 'Restart=no',
- 'ExecStart=',
- 'ExecReload=',
- ]
- if use_valgrind:
- drop_in += [
- 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin,
- f'ExecReload=valgrind {networkctl_bin} reload',
- 'PrivateTmp=yes'
+ create_service_dropin('systemd-networkd', networkd_bin,
+ f'{networkctl_bin} reload',
+ ['[Service]', 'Restart=no', '[Unit]', 'StartLimitIntervalSec=0'])
+ create_service_dropin('systemd-resolved', resolved_bin)
+ create_service_dropin('systemd-timesyncd', timesyncd_bin)
+
+ # TODO: also run udevd with sanitizers, valgrind, or coverage
+ #create_service_dropin('systemd-udevd', udevd_bin,
+ # f'{udevadm_bin} control --reload --timeout 0')
+ create_unit_dropin(
+ 'systemd-udevd.service',
+ [
+ '[Service]',
+ 'ExecStart=',
+ f'ExecStart=!!{udevd_bin}',
+ 'ExecReload=',
+ f'ExecReload={udevadm_bin} control --reload --timeout 0',
]
- else:
- drop_in += [
- 'ExecStart=!!' + networkd_bin,
- f'ExecReload={networkctl_bin} reload',
- ]
- if enable_debug:
- drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
- if asan_options:
- drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"']
- if lsan_options:
- drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"']
- if ubsan_options:
- drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"']
- if asan_options or lsan_options or ubsan_options:
- drop_in += ['SystemCallFilter=']
- if use_valgrind or asan_options or lsan_options or ubsan_options:
- drop_in += ['MemoryDenyWriteExecute=no']
- if with_coverage:
- drop_in += [
- 'ProtectSystem=no',
- 'ProtectHome=no',
- ]
-
- mkdir_p('/run/systemd/system/systemd-networkd.service.d')
- with open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode='w', encoding='utf-8') as f:
- f.write('\n'.join(drop_in))
-
- drop_in = [
- '[Service]',
- 'Restart=no',
- 'ExecStart=',
- ]
- if use_valgrind:
- drop_in += ['ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + resolved_bin]
- else:
- drop_in += ['ExecStart=!!' + resolved_bin]
- if enable_debug:
- drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
- if asan_options:
- drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"']
- if lsan_options:
- drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"']
- if ubsan_options:
- drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"']
- if asan_options or lsan_options or ubsan_options:
- drop_in += ['SystemCallFilter=']
- if use_valgrind or asan_options or lsan_options or ubsan_options:
- drop_in += ['MemoryDenyWriteExecute=no']
- if with_coverage:
- drop_in += [
- 'ProtectSystem=no',
- 'ProtectHome=no',
+ )
+ create_unit_dropin(
+ 'systemd-networkd.socket',
+ [
+ '[Unit]',
+ 'StartLimitIntervalSec=0',
]
-
- mkdir_p('/run/systemd/system/systemd-resolved.service.d')
- with open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode='w', encoding='utf-8') as f:
- f.write('\n'.join(drop_in))
-
- drop_in = [
- '[Service]',
- 'ExecStart=',
- 'ExecStart=!!' + udevd_bin,
- ]
-
- mkdir_p('/run/systemd/system/systemd-udevd.service.d')
- with open('/run/systemd/system/systemd-udevd.service.d/00-override.conf', mode='w', encoding='utf-8') as f:
- f.write('\n'.join(drop_in))
+ )
check_output('systemctl daemon-reload')
print(check_output('systemctl cat systemd-networkd.service'))
print(check_output('systemctl cat systemd-resolved.service'))
+ print(check_output('systemctl cat systemd-timesyncd.service'))
print(check_output('systemctl cat systemd-udevd.service'))
check_output('systemctl restart systemd-resolved.service')
+ check_output('systemctl restart systemd-timesyncd.service')
check_output('systemctl restart systemd-udevd.service')
def tearDownModule():
restore_timezone()
rm_rf('/run/systemd/system/systemd-networkd.service.d')
+ rm_rf('/run/systemd/system/systemd-networkd.socket.d')
rm_rf('/run/systemd/system/systemd-resolved.service.d')
+ rm_rf('/run/systemd/system/systemd-timesyncd.service.d')
rm_rf('/run/systemd/system/systemd-udevd.service.d')
check_output('systemctl daemon-reload')
check_output('systemctl restart systemd-udevd.service')
try:
check_output(*args, env=wait_online_env)
except subprocess.CalledProcessError as e:
- print(e.stdout) # show logs only on failure
+ # show detailed status on failure
for link in links_with_operstate:
name = link.split(':')[0]
if link_exists(name):
self.assertRegex(output, 'link/ether 12:34:56:78:9a:bf')
self.assertRegex(output, 'mtu 1800')
- def test_tun(self):
- copy_network_unit('25-tun.netdev')
+ def test_tuntap(self):
+ copy_network_unit('25-tun.netdev', '25-tap.netdev')
start_networkd()
- self.wait_online(['tun99:off'], setup_state='unmanaged')
+ self.wait_online(['testtun99:off', 'testtap99:off'], setup_state='unmanaged')
- output = check_output('ip -d link show tun99')
+ output = check_output('ip -d link show testtun99')
print(output)
# Old ip command does not support IFF_ flags
self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
- def test_tap(self):
- copy_network_unit('25-tap.netdev')
- start_networkd()
-
- self.wait_online(['tap99:off'], setup_state='unmanaged')
-
- output = check_output('ip -d link show tap99')
+ output = check_output('ip -d link show testtap99')
print(output)
# Old ip command does not support IFF_ flags
self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
print(output)
self.assertEqual(output, '')
- def test_qdisc(self):
- copy_network_unit('25-qdisc-clsact-and-htb.network', '12-dummy.netdev',
- '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev')
- check_output('modprobe sch_teql max_equalizers=2')
+class NetworkdTCTests(unittest.TestCase, Utilities):
+
+ def setUp(self):
+ setup_common()
+
+ def tearDown(self):
+ tear_down_common()
+
+ @expectedFailureIfModuleIsNotAvailable('sch_cake')
+ def test_qdisc_cake(self):
+ copy_network_unit('25-qdisc-cake.network', '12-dummy.netdev')
start_networkd()
- self.wait_online(['dummy98:routable', 'test1:routable'])
+ self.wait_online(['dummy98:routable'])
- output = check_output('tc qdisc show dev test1')
+ output = check_output('tc qdisc show dev dummy98')
print(output)
- self.assertRegex(output, 'qdisc netem')
- self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
- self.assertRegex(output, 'qdisc ingress')
+ self.assertIn('qdisc cake 3a: root', output)
+ self.assertIn('bandwidth 500Mbit', output)
+ self.assertIn('autorate-ingress', output)
+ self.assertIn('diffserv8', output)
+ self.assertIn('dual-dsthost', output)
+ self.assertIn(' nat', output)
+ self.assertIn(' wash', output)
+ self.assertIn(' split-gso', output)
+ self.assertIn(' raw', output)
+ self.assertIn(' atm', output)
+ self.assertIn('overhead 128', output)
+ self.assertIn('mpu 20', output)
+ self.assertIn('fwmark 0xff00', output)
+
+ @expectedFailureIfModuleIsNotAvailable('sch_codel')
+ def test_qdisc_codel(self):
+ copy_network_unit('25-qdisc-codel.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
output = check_output('tc qdisc show dev dummy98')
print(output)
- self.assertRegex(output, 'qdisc clsact')
+ self.assertRegex(output, 'qdisc codel 33: root')
+ self.assertRegex(output, 'limit 2000p target 10(.0)?ms ce_threshold 100(.0)?ms interval 50(.0)?ms ecn')
- self.assertRegex(output, 'qdisc htb 2: root')
- self.assertRegex(output, r'default (0x30|30)')
+ @expectedFailureIfModuleIsNotAvailable('sch_drr')
+ def test_qdisc_drr(self):
+ copy_network_unit('25-qdisc-drr.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
- self.assertRegex(output, 'qdisc netem 30: parent 2:30')
- self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
- self.assertRegex(output, 'qdisc fq_codel')
- self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10(.0)?ms ce_threshold 100(.0)?ms interval 200(.0)?ms memory_limit 64Mb ecn')
+ output = check_output('tc qdisc show dev dummy98')
+ print(output)
+ self.assertRegex(output, 'qdisc drr 2: root')
+ output = check_output('tc class show dev dummy98')
+ print(output)
+ self.assertRegex(output, 'class drr 2:30 root quantum 2000b')
+
+ @expectedFailureIfModuleIsNotAvailable('sch_ets')
+ def test_qdisc_ets(self):
+ copy_network_unit('25-qdisc-ets.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
- self.assertRegex(output, 'qdisc teql1 31: parent 2:31')
+ output = check_output('tc qdisc show dev dummy98')
+ print(output)
+
+ self.assertRegex(output, 'qdisc ets 3a: root')
+ self.assertRegex(output, 'bands 10 strict 3')
+ self.assertRegex(output, 'quanta 1 2 3 4 5')
+ self.assertRegex(output, 'priomap 3 4 5 6 7')
- self.assertRegex(output, 'qdisc fq 32: parent 2:32')
+ @expectedFailureIfModuleIsNotAvailable('sch_fq')
+ def test_qdisc_fq(self):
+ copy_network_unit('25-qdisc-fq.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
+
+ output = check_output('tc qdisc show dev dummy98')
+ print(output)
+ self.assertRegex(output, 'qdisc fq 32: root')
self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511')
self.assertRegex(output, 'quantum 1500')
self.assertRegex(output, 'initial_quantum 13000')
self.assertRegex(output, 'maxrate 1Mbit')
- self.assertRegex(output, 'qdisc codel 33: parent 2:33')
- self.assertRegex(output, 'limit 2000p target 10(.0)?ms ce_threshold 100(.0)?ms interval 50(.0)?ms ecn')
+ @expectedFailureIfModuleIsNotAvailable('sch_fq_codel')
+ def test_qdisc_fq_codel(self):
+ copy_network_unit('25-qdisc-fq_codel.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
- self.assertRegex(output, 'qdisc fq_codel 34: parent 2:34')
+ output = check_output('tc qdisc show dev dummy98')
+ print(output)
+ self.assertRegex(output, 'qdisc fq_codel 34: root')
self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10(.0)?ms ce_threshold 100(.0)?ms interval 200(.0)?ms memory_limit 64Mb ecn')
- self.assertRegex(output, 'qdisc tbf 35: parent 2:35')
- self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70(.0)?ms')
+ @expectedFailureIfModuleIsNotAvailable('sch_fq_pie')
+ def test_qdisc_fq_pie(self):
+ copy_network_unit('25-qdisc-fq_pie.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
- self.assertRegex(output, 'qdisc sfq 36: parent 2:36')
- self.assertRegex(output, 'perturb 5sec')
+ output = check_output('tc qdisc show dev dummy98')
+ print(output)
- self.assertRegex(output, 'qdisc pfifo 37: parent 2:37')
- self.assertRegex(output, 'limit 100000p')
+ self.assertRegex(output, 'qdisc fq_pie 3a: root')
+ self.assertRegex(output, 'limit 200000p')
- self.assertRegex(output, 'qdisc gred 38: parent 2:38')
+ @expectedFailureIfModuleIsNotAvailable('sch_gred')
+ def test_qdisc_gred(self):
+ copy_network_unit('25-qdisc-gred.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
+
+ output = check_output('tc qdisc show dev dummy98')
+ print(output)
+ self.assertRegex(output, 'qdisc gred 38: root')
self.assertRegex(output, 'vqs 12 default 10 grio')
- self.assertRegex(output, 'qdisc sfb 39: parent 2:39')
- self.assertRegex(output, 'limit 200000')
+ @expectedFailureIfModuleIsNotAvailable('sch_hhf')
+ def test_qdisc_hhf(self):
+ copy_network_unit('25-qdisc-hhf.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
+
+ output = check_output('tc qdisc show dev dummy98')
+ print(output)
+ self.assertRegex(output, 'qdisc hhf 3a: root')
+ self.assertRegex(output, 'limit 1022p')
+
+ @expectedFailureIfModuleIsNotAvailable('sch_htb')
+ def test_qdisc_htb_fifo(self):
+ copy_network_unit('25-qdisc-htb-fifo.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
+
+ output = check_output('tc qdisc show dev dummy98')
+ print(output)
+ self.assertRegex(output, 'qdisc htb 2: root')
+ self.assertRegex(output, r'default (0x30|30)')
+
+ self.assertRegex(output, 'qdisc pfifo 37: parent 2:37')
+ self.assertRegex(output, 'limit 100000p')
self.assertRegex(output, 'qdisc bfifo 3a: parent 2:3a')
self.assertRegex(output, 'limit 1000000')
output = check_output('tc -d class show dev dummy98')
print(output)
- self.assertRegex(output, 'class htb 2:30 root leaf 30:')
- self.assertRegex(output, 'class htb 2:31 root leaf 31:')
- self.assertRegex(output, 'class htb 2:32 root leaf 32:')
- self.assertRegex(output, 'class htb 2:33 root leaf 33:')
- self.assertRegex(output, 'class htb 2:34 root leaf 34:')
- self.assertRegex(output, 'class htb 2:35 root leaf 35:')
- self.assertRegex(output, 'class htb 2:36 root leaf 36:')
self.assertRegex(output, 'class htb 2:37 root leaf 37:')
- self.assertRegex(output, 'class htb 2:38 root leaf 38:')
- self.assertRegex(output, 'class htb 2:39 root leaf 39:')
self.assertRegex(output, 'class htb 2:3a root leaf 3a:')
self.assertRegex(output, 'class htb 2:3b root leaf 3b:')
self.assertRegex(output, 'class htb 2:3c root leaf 3c:')
self.assertRegex(output, 'burst 123456')
self.assertRegex(output, 'cburst 123457')
- def test_qdisc2(self):
- copy_network_unit('25-qdisc-drr.network', '12-dummy.netdev',
- '25-qdisc-qfq.network', '11-dummy.netdev')
+ @expectedFailureIfModuleIsNotAvailable('sch_ingress')
+ def test_qdisc_ingress(self):
+ copy_network_unit('25-qdisc-clsact.network', '12-dummy.netdev',
+ '25-qdisc-ingress.network', '11-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable', 'test1:routable'])
output = check_output('tc qdisc show dev dummy98')
print(output)
- self.assertRegex(output, 'qdisc drr 2: root')
- output = check_output('tc class show dev dummy98')
- print(output)
- self.assertRegex(output, 'class drr 2:30 root quantum 2000b')
+ self.assertRegex(output, 'qdisc clsact')
output = check_output('tc qdisc show dev test1')
print(output)
- self.assertRegex(output, 'qdisc qfq 2: root')
- output = check_output('tc class show dev test1')
- print(output)
- self.assertRegex(output, 'class qfq 2:30 root weight 2 maxpkt 16000')
- self.assertRegex(output, 'class qfq 2:31 root weight 10 maxpkt 8000')
+ self.assertRegex(output, 'qdisc ingress')
- @expectedFailureIfCAKEIsNotAvailable()
- def test_qdisc_cake(self):
- copy_network_unit('25-qdisc-cake.network', '12-dummy.netdev')
+ @expectedFailureIfModuleIsNotAvailable('sch_netem')
+ def test_qdisc_netem(self):
+ copy_network_unit('25-qdisc-netem.network', '12-dummy.netdev',
+ '25-qdisc-netem-compat.network', '11-dummy.netdev')
start_networkd()
- self.wait_online(['dummy98:routable'])
+ self.wait_online(['dummy98:routable', 'test1:routable'])
output = check_output('tc qdisc show dev dummy98')
print(output)
- self.assertIn('qdisc cake 3a: root', output)
- self.assertIn('bandwidth 500Mbit', output)
- self.assertIn('autorate-ingress', output)
- self.assertIn('diffserv8', output)
- self.assertIn('dual-dsthost', output)
- self.assertIn(' nat', output)
- self.assertIn(' wash', output)
- self.assertIn(' split-gso', output)
- self.assertIn(' raw', output)
- self.assertIn(' atm', output)
- self.assertIn('overhead 128', output)
- self.assertIn('mpu 20', output)
- self.assertIn('fwmark 0xff00', output)
+ self.assertRegex(output, 'qdisc netem 30: root')
+ self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
- @expectedFailureIfPIEIsNotAvailable()
+ output = check_output('tc qdisc show dev test1')
+ print(output)
+ self.assertRegex(output, 'qdisc netem [0-9a-f]*: root')
+ self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
+
+ @expectedFailureIfModuleIsNotAvailable('sch_pie')
def test_qdisc_pie(self):
copy_network_unit('25-qdisc-pie.network', '12-dummy.netdev')
start_networkd()
self.assertRegex(output, 'qdisc pie 3a: root')
self.assertRegex(output, 'limit 200000')
- @expectedFailureIfHHFIsNotAvailable()
- def test_qdisc_hhf(self):
- copy_network_unit('25-qdisc-hhf.network', '12-dummy.netdev')
+ @expectedFailureIfModuleIsNotAvailable('sch_qfq')
+ def test_qdisc_qfq(self):
+ copy_network_unit('25-qdisc-qfq.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
output = check_output('tc qdisc show dev dummy98')
print(output)
- self.assertRegex(output, 'qdisc hhf 3a: root')
- self.assertRegex(output, 'limit 1022p')
+ self.assertRegex(output, 'qdisc qfq 2: root')
+ output = check_output('tc class show dev dummy98')
+ print(output)
+ self.assertRegex(output, 'class qfq 2:30 root weight 2 maxpkt 16000')
+ self.assertRegex(output, 'class qfq 2:31 root weight 10 maxpkt 8000')
- @expectedFailureIfETSIsNotAvailable()
- def test_qdisc_ets(self):
- copy_network_unit('25-qdisc-ets.network', '12-dummy.netdev')
+ @expectedFailureIfModuleIsNotAvailable('sch_sfb')
+ def test_qdisc_sfb(self):
+ copy_network_unit('25-qdisc-sfb.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
output = check_output('tc qdisc show dev dummy98')
print(output)
+ self.assertRegex(output, 'qdisc sfb 39: root')
+ self.assertRegex(output, 'limit 200000')
- self.assertRegex(output, 'qdisc ets 3a: root')
- self.assertRegex(output, 'bands 10 strict 3')
- self.assertRegex(output, 'quanta 1 2 3 4 5')
- self.assertRegex(output, 'priomap 3 4 5 6 7')
+ @expectedFailureIfModuleIsNotAvailable('sch_sfq')
+ def test_qdisc_sfq(self):
+ copy_network_unit('25-qdisc-sfq.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_online(['dummy98:routable'])
- @expectedFailureIfFQPIEIsNotAvailable()
- def test_qdisc_fq_pie(self):
- copy_network_unit('25-qdisc-fq_pie.network', '12-dummy.netdev')
+ output = check_output('tc qdisc show dev dummy98')
+ print(output)
+ self.assertRegex(output, 'qdisc sfq 36: root')
+ self.assertRegex(output, 'perturb 5sec')
+
+ @expectedFailureIfModuleIsNotAvailable('sch_tbf')
+ def test_qdisc_tbf(self):
+ copy_network_unit('25-qdisc-tbf.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
output = check_output('tc qdisc show dev dummy98')
print(output)
+ self.assertRegex(output, 'qdisc tbf 35: root')
+ self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70(.0)?ms')
- self.assertRegex(output, 'qdisc fq_pie 3a: root')
- self.assertRegex(output, 'limit 200000p')
+ @expectedFailureIfModuleIsNotAvailable('sch_teql')
+ def test_qdisc_teql(self):
+ call_quiet('rmmod sch_teql')
+
+ copy_network_unit('25-qdisc-teql.network', '12-dummy.netdev')
+ start_networkd()
+ self.wait_links('dummy98')
+ check_output('modprobe sch_teql max_equalizers=2')
+ self.wait_online(['dummy98:routable'])
+
+ output = check_output('tc qdisc show dev dummy98')
+ print(output)
+ self.assertRegex(output, 'qdisc teql1 31: root')
+
+class NetworkWaitOnlineTests(unittest.TestCase, Utilities):
+
+ def setUp(self):
+ setup_common()
+
+ def tearDown(self):
+ tear_down_common()
def test_wait_online_ipv4(self):
copy_network_unit('25-veth.netdev', '25-dhcp-server-with-ipv6-prefix.network', '25-dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network')
self.check_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress', '1', allow_enoent=True)
self.check_bridge_port_attr('bridge99', 'dummy98', 'learning', '0')
self.check_bridge_port_attr('bridge99', 'dummy98', 'priority', '23')
- self.check_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard', '1')
- self.check_bridge_port_attr('bridge99', 'dummy98', 'root_block', '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard', '0')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'root_block', '0')
def test_bridge_property(self):
copy_network_unit('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
self.check_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress', '1', allow_enoent=True)
self.check_bridge_port_attr('bridge99', 'dummy98', 'learning', '0')
self.check_bridge_port_attr('bridge99', 'dummy98', 'priority', '23')
- self.check_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard', '1')
- self.check_bridge_port_attr('bridge99', 'dummy98', 'root_block', '1')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard', '0')
+ self.check_bridge_port_attr('bridge99', 'dummy98', 'root_block', '0')
output = check_output('bridge -d link show test1')
print(output)
f.write('[Link]\nSR-IOVVirtualFunctions=4\n')
udev_reload()
- call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1')
+ call(*udevadm_cmd, 'trigger', '--action=add', '--settle', '/sys/devices/netdevsim99/net/eni99np1')
output = check_output('ip link show dev eni99np1')
print(output)
f.write('[Link]\nSR-IOVVirtualFunctions=\n')
udev_reload()
- call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1')
+ call(*udevadm_cmd, 'trigger', '--action=add', '--settle', '/sys/devices/netdevsim99/net/eni99np1')
output = check_output('ip link show dev eni99np1')
print(output)
f.write('[Link]\nSR-IOVVirtualFunctions=2\n')
udev_reload()
- call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1')
+ call(*udevadm_cmd, 'trigger', '--action=add', '--settle', '/sys/devices/netdevsim99/net/eni99np1')
output = check_output('ip link show dev eni99np1')
print(output)
f.write('[Link]\nSR-IOVVirtualFunctions=\n')
udev_reload()
- call('udevadm trigger --action add --settle /sys/devices/netdevsim99/net/eni99np1')
+ call(*udevadm_cmd, 'trigger', '--action=add', '--settle', '/sys/devices/netdevsim99/net/eni99np1')
output = check_output('ip link show dev eni99np1')
print(output)
parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
+ parser.add_argument('--timesyncd', help='Path to systemd-timesyncd', dest='timesyncd_bin')
parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
+ parser.add_argument('--udevadm', help='Path to udevadm', dest='udevadm_bin')
parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
ns, unknown_args = parser.parse_known_args(namespace=unittest)
if ns.build_dir:
- if ns.networkd_bin or ns.resolved_bin or ns.udevd_bin or ns.wait_online_bin or ns.networkctl_bin or ns.resolvectl_bin or ns.timedatectl_bin:
- print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
+ if ns.networkd_bin or ns.resolved_bin or ns.timesyncd_bin or ns.udevd_bin or \
+ ns.wait_online_bin or ns.networkctl_bin or ns.resolvectl_bin or ns.timedatectl_bin or ns.udevadm_bin:
+ print('WARNING: --networkd, --resolved, --timesyncd, --udevd, --wait-online, --networkctl, --resolvectl, --timedatectl, or --udevadm options are ignored when --build-dir is specified.')
networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
+ timesyncd_bin = os.path.join(ns.build_dir, 'systemd-timesyncd')
udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
+ udevadm_bin = os.path.join(ns.build_dir, 'udevadm')
else:
if ns.networkd_bin:
networkd_bin = ns.networkd_bin
if ns.resolved_bin:
resolved_bin = ns.resolved_bin
+ if ns.timesyncd_bin:
+ timesyncd_bin = ns.timesyncd_bin
if ns.udevd_bin:
udevd_bin = ns.udevd_bin
if ns.wait_online_bin:
resolvectl_bin = ns.resolvectl_bin
if ns.timedatectl_bin:
timedatectl_bin = ns.timedatectl_bin
+ if ns.udevadm_bin:
+ udevadm_bin = ns.udevadm_bin
use_valgrind = ns.use_valgrind
enable_debug = ns.enable_debug
with_coverage = ns.with_coverage
if use_valgrind:
- networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
- resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
- timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
- wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
- else:
- networkctl_cmd = [networkctl_bin]
- resolvectl_cmd = [resolvectl_bin]
- timedatectl_cmd = [timedatectl_bin]
- wait_online_cmd = [wait_online_bin]
+ # Do not forget the trailing space.
+ valgrind_cmd = 'valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all '
+
+ networkctl_cmd = valgrind_cmd.split() + [networkctl_bin]
+ resolvectl_cmd = valgrind_cmd.split() + [resolvectl_bin]
+ timedatectl_cmd = valgrind_cmd.split() + [timedatectl_bin]
+ udevadm_cmd = valgrind_cmd.split() + [udevadm_bin]
+ wait_online_cmd = valgrind_cmd.split() + [wait_online_bin]
if asan_options:
env.update({'ASAN_OPTIONS': asan_options})
env.update({'LSAN_OPTIONS': lsan_options})
if ubsan_options:
env.update({'UBSAN_OPTIONS': ubsan_options})
+ if use_valgrind:
+ env.update({'SYSTEMD_MEMPOOL': '0'})
wait_online_env = env.copy()
if enable_debug:
# utility functions for shell tests
assert_true() {(
- local rc
-
set +ex
+ local rc
+
"$@"
rc=$?
if [[ $rc -ne 0 ]]; then
)}
assert_rc() {(
- local rc exp="${1?}"
-
set +ex
+ local rc exp="${1?}"
+
shift
"$@"
rc=$?
--- /dev/null
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -ex
+set -o pipefail
+
+# shellcheck source=test/units/assert.sh
+. "$(dirname "$0")"/assert.sh
+
+wait_service_active() {(
+ set +ex
+ for (( i = 0; i < 20; i++ )); do
+ if (( i != 0 )); then sleep 0.5; fi
+ if systemctl --quiet is-active "${1?}"; then
+ return 0
+ fi
+ done
+ return 1
+)}
+
+wait_service_inactive() {(
+ set +ex
+ for (( i = 0; i < 20; i++ )); do
+ if (( i != 0 )); then sleep 0.5; fi
+ systemctl --quiet is-active "${1?}"
+ if [[ "$?" == "3" ]]; then
+ return 0
+ fi
+ done
+ return 1
+)}
+
+mkdir -p /run/systemd/system
+cat >/run/systemd/system/both.service <<EOF
+[Service]
+ExecStart=sleep 1000
+EOF
+
+cat >/run/systemd/system/on-add.service <<EOF
+[Service]
+ExecStart=sleep 1000
+EOF
+
+cat >/run/systemd/system/on-change.service <<EOF
+[Service]
+ExecStart=sleep 1000
+EOF
+
+systemctl daemon-reload
+
+mkdir -p /run/udev/rules.d/
+cat >/run/udev/rules.d/50-testsuite.rules <<EOF
+SUBSYSTEM=="net", KERNEL=="dummy9?", OPTIONS="log_level=debug"
+SUBSYSTEM=="net", KERNEL=="dummy9?", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="both.service", ENV{SYSTEMD_WANTS}+="on-add.service"
+SUBSYSTEM=="net", KERNEL=="dummy9?", ACTION=="change", TAG+="systemd", ENV{SYSTEMD_WANTS}+="both.service", ENV{SYSTEMD_WANTS}+="on-change.service"
+EOF
+
+udevadm control --reload
+
+# StopWhenUnneeded=no
+ip link add dummy99 type dummy
+udevadm wait --settle --timeout=30 /sys/class/net/dummy99
+wait_service_active both.service
+wait_service_active on-add.service
+assert_rc 3 systemctl --quiet is-active on-change.service
+systemctl stop both.service on-add.service
+
+udevadm trigger --action=change --settle /sys/class/net/dummy99
+udevadm info /sys/class/net/dummy99
+wait_service_active both.service
+assert_rc 3 systemctl --quiet is-active on-add.service
+wait_service_active on-change.service
+systemctl stop both.service on-change.service
+
+ip link del dummy99
+udevadm wait --settle --timeout=30 --removed /sys/class/net/dummy99
+assert_rc 3 systemctl --quiet is-active both.service
+assert_rc 3 systemctl --quiet is-active on-add.service
+assert_rc 3 systemctl --quiet is-active on-change.service
+
+# StopWhenUnneeded=yes
+cat >/run/systemd/system/both.service <<EOF
+[Unit]
+StopWhenUnneeded=yes
+
+[Service]
+ExecStart=sleep 1000
+Type=simple
+EOF
+
+cat >/run/systemd/system/on-add.service <<EOF
+[Unit]
+StopWhenUnneeded=yes
+
+[Service]
+ExecStart=sleep 1000
+Type=simple
+EOF
+
+cat >/run/systemd/system/on-change.service <<EOF
+[Unit]
+StopWhenUnneeded=yes
+
+[Service]
+ExecStart=echo changed
+RemainAfterExit=true
+Type=oneshot
+EOF
+
+systemctl daemon-reload
+
+# StopWhenUnneeded=yes (single device, only add event)
+ip link add dummy99 type dummy
+udevadm wait --settle --timeout=30 /sys/class/net/dummy99
+wait_service_active both.service
+wait_service_active on-add.service
+assert_rc 3 systemctl --quiet is-active on-change.service
+
+ip link del dummy99
+udevadm wait --settle --timeout=30 --removed /sys/class/net/dummy99
+wait_service_inactive both.service
+wait_service_inactive on-add.service
+assert_rc 3 systemctl --quiet is-active on-change.service
+
+# StopWhenUnneeded=yes (single device, add and change event)
+ip link add dummy99 type dummy
+udevadm wait --settle --timeout=30 /sys/class/net/dummy99
+wait_service_active both.service
+wait_service_active on-add.service
+assert_rc 3 systemctl --quiet is-active on-change.service
+
+udevadm trigger --action=change --settle /sys/class/net/dummy99
+assert_rc 0 systemctl --quiet is-active both.service
+wait_service_inactive on-add.service
+wait_service_active on-change.service
+
+ip link del dummy99
+udevadm wait --settle --timeout=30 --removed /sys/class/net/dummy99
+wait_service_inactive both.service
+assert_rc 3 systemctl --quiet is-active on-add.service
+wait_service_inactive on-change.service
+
+# StopWhenUnneeded=yes (multiple devices, only add events)
+ip link add dummy99 type dummy
+udevadm wait --settle --timeout=30 /sys/class/net/dummy99
+wait_service_active both.service
+wait_service_active on-add.service
+assert_rc 3 systemctl --quiet is-active on-change.service
+
+ip link add dummy98 type dummy
+udevadm wait --settle --timeout=30 /sys/class/net/dummy98
+assert_rc 0 systemctl --quiet is-active both.service
+assert_rc 0 systemctl --quiet is-active on-add.service
+assert_rc 3 systemctl --quiet is-active on-change.service
+
+ip link del dummy99
+udevadm wait --settle --timeout=30 --removed /sys/class/net/dummy99
+assert_rc 0 systemctl --quiet is-active both.service
+assert_rc 0 systemctl --quiet is-active on-add.service
+assert_rc 3 systemctl --quiet is-active on-change.service
+
+ip link del dummy98
+udevadm wait --settle --timeout=30 --removed /sys/class/net/dummy98
+wait_service_inactive both.service
+wait_service_inactive on-add.service
+assert_rc 3 systemctl --quiet is-active on-change.service
+
+# StopWhenUnneeded=yes (multiple devices, add and change events)
+ip link add dummy99 type dummy
+udevadm wait --settle --timeout=30 /sys/class/net/dummy99
+wait_service_active both.service
+wait_service_active on-add.service
+assert_rc 3 systemctl --quiet is-active on-change.service
+
+ip link add dummy98 type dummy
+udevadm wait --settle --timeout=30 /sys/class/net/dummy98
+assert_rc 0 systemctl --quiet is-active both.service
+assert_rc 0 systemctl --quiet is-active on-add.service
+assert_rc 3 systemctl --quiet is-active on-change.service
+
+udevadm trigger --action=change --settle /sys/class/net/dummy99
+assert_rc 0 systemctl --quiet is-active both.service
+assert_rc 0 systemctl --quiet is-active on-add.service
+wait_service_active on-change.service
+
+ip link del dummy98
+udevadm wait --settle --timeout=30 --removed /sys/class/net/dummy98
+assert_rc 0 systemctl --quiet is-active both.service
+wait_service_inactive on-add.service
+assert_rc 0 systemctl --quiet is-active on-change.service
+
+ip link del dummy99
+udevadm wait --settle --timeout=30 --removed /sys/class/net/dummy99
+wait_service_inactive both.service
+assert_rc 3 systemctl --quiet is-active on-add.service
+wait_service_inactive on-change.service
+
+# cleanup
+rm -f /run/udev/rules.d/50-testsuite.rules
+udevadm control --reload
+
+rm -f /run/systemd/system/on-add.service
+rm -f /run/systemd/system/on-change.service
+systemctl daemon-reload
+
+exit 0
echo -n passphrase >/tmp/passphrase
cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom $img /tmp/passphrase
+# Unlocking via keyfile
+systemd-cryptenroll --unlock-key-file=/tmp/passphrase --tpm2-device=auto $img
+
# Enroll unlock with default PCR policy
env PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto $img
/usr/lib/systemd/systemd-cryptsetup attach test-volume $img - tpm2-device=auto,headless=1
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
-# The official unmodified version of the script can be found at
-# https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh
+set -eux
-set -e
+COVERITY_SCAN_TOOL_BASE="/tmp/coverity-scan-analysis"
+COVERITY_SCAN_PROJECT_NAME="systemd/systemd"
-# Declare build command
-COVERITY_SCAN_BUILD_COMMAND="ninja -C cov-build"
+function coverity_install_script {
+ local platform tool_url tool_archive
-# Environment check
-# Use default values if not set
-SCAN_URL=${SCAN_URL:="https://scan.coverity.com"}
-TOOL_BASE=${TOOL_BASE:="/tmp/coverity-scan-analysis"}
-UPLOAD_URL=${UPLOAD_URL:="https://scan.coverity.com/builds"}
+ platform=$(uname)
+ tool_url="https://scan.coverity.com/download/${platform}"
+ tool_archive="/tmp/cov-analysis-${platform}.tgz"
-# These must be set by environment
-echo -e "\033[33;1mNote: COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN are available on Project Settings page on scan.coverity.com\033[0m"
-[ -z "$COVERITY_SCAN_PROJECT_NAME" ] && echo "ERROR: COVERITY_SCAN_PROJECT_NAME must be set" && exit 1
-[ -z "$COVERITY_SCAN_NOTIFICATION_EMAIL" ] && echo "ERROR: COVERITY_SCAN_NOTIFICATION_EMAIL must be set" && exit 1
-[ -z "$COVERITY_SCAN_BRANCH_PATTERN" ] && echo "ERROR: COVERITY_SCAN_BRANCH_PATTERN must be set" && exit 1
-[ -z "$COVERITY_SCAN_BUILD_COMMAND" ] && echo "ERROR: COVERITY_SCAN_BUILD_COMMAND must be set" && exit 1
-[ -z "$COVERITY_SCAN_TOKEN" ] && echo "ERROR: COVERITY_SCAN_TOKEN must be set" && exit 1
+ set +x # this is supposed to hide COVERITY_SCAN_TOKEN
+ echo -e "\033[33;1mDownloading Coverity Scan Analysis Tool...\033[0m"
+ wget -nv -O "$tool_archive" "$tool_url" --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=${COVERITY_SCAN_TOKEN:?}"
+ set -x
-# Verify this branch should run
-if [[ "${CURRENT_REF^^}" =~ "${COVERITY_SCAN_BRANCH_PATTERN^^}" ]]; then
- echo -e "\033[33;1mCoverity Scan configured to run on branch ${CURRENT_REF}\033[0m"
-else
- echo -e "\033[33;1mCoverity Scan NOT configured to run on branch ${CURRENT_REF}\033[0m"
- exit 1
-fi
-
-# Verify upload is permitted
-AUTH_RES=`curl -s --form project="$COVERITY_SCAN_PROJECT_NAME" --form token="$COVERITY_SCAN_TOKEN" $SCAN_URL/api/upload_permitted`
-if [ "$AUTH_RES" = "Access denied" ]; then
- echo -e "\033[33;1mCoverity Scan API access denied. Check COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN.\033[0m"
- exit 1
-else
- AUTH=`echo $AUTH_RES | jq .upload_permitted`
- if [ "$AUTH" = "true" ]; then
- echo -e "\033[33;1mCoverity Scan analysis authorized per quota.\033[0m"
- else
- WHEN=`echo $AUTH_RES | jq .next_upload_permitted_at`
- echo -e "\033[33;1mCoverity Scan analysis NOT authorized until $WHEN.\033[0m"
- exit 1
- fi
-fi
-
-TOOL_DIR=`find $TOOL_BASE -type d -name 'cov-analysis*'`
-export PATH="$TOOL_DIR/bin:$PATH"
-
-# Disable CCACHE for cov-build to compilation units correctly
-export CCACHE_DISABLE=1
-
-# FUNCTION DEFINITIONS
-# --------------------
-_help()
-{
- # displays help and exits
- cat <<-EOF
- USAGE: $0 [CMD] [OPTIONS]
-
- CMD
- build Issue Coverity build
- upload Upload coverity archive for analysis
- Note: By default, archive is created from default results directory.
- To provide custom archive or results directory, see --result-dir
- and --tar options below.
-
- OPTIONS
- -h,--help Display this menu and exits
-
- Applicable to build command
- ---------------------------
- -o,--out-dir Specify Coverity intermediate directory (defaults to 'cov-int')
- -t,--tar bool, archive the output to .tgz file (defaults to false)
-
- Applicable to upload command
- ----------------------------
- -d, --result-dir Specify result directory if different from default ('cov-int')
- -t, --tar ARCHIVE Use custom .tgz archive instead of intermediate directory or pre-archived .tgz
- (by default 'analysis-result.tgz'
- EOF
- return;
-}
-
-_pack()
-{
- RESULTS_ARCHIVE=${RESULTS_ARCHIVE:-'analysis-results.tgz'}
-
- echo -e "\033[33;1mTarring Coverity Scan Analysis results...\033[0m"
- tar czf $RESULTS_ARCHIVE $RESULTS_DIR
- SHA=`git rev-parse --short HEAD`
-
- PACKED=true
+ mkdir -p "$COVERITY_SCAN_TOOL_BASE"
+ pushd "$COVERITY_SCAN_TOOL_BASE"
+ tar xzf "$tool_archive"
+ popd
}
+function run_coverity {
+ local results_dir tool_dir results_archive sha response status_code
-_build()
-{
- echo -e "\033[33;1mRunning Coverity Scan Analysis Tool...\033[0m"
- local _cov_build_options=""
- #local _cov_build_options="--return-emit-failures 8 --parse-error-threshold 85"
- eval "${COVERITY_SCAN_BUILD_COMMAND_PREPEND}"
- COVERITY_UNSUPPORTED=1 cov-build --dir $RESULTS_DIR $_cov_build_options sh -c "$COVERITY_SCAN_BUILD_COMMAND"
- cov-import-scm --dir $RESULTS_DIR --scm git --log $RESULTS_DIR/scm_log.txt
+ results_dir="cov-int"
+ tool_dir=$(find "$COVERITY_SCAN_TOOL_BASE" -type d -name 'cov-analysis*')
+ results_archive="analysis-results.tgz"
+ sha=$(git rev-parse --short HEAD)
- if [ $? != 0 ]; then
- echo -e "\033[33;1mCoverity Scan Build failed: $TEXT.\033[0m"
- return 1
- fi
-
- [ -z $TAR ] || [ $TAR = false ] && return 0
+ meson -Dman=false build
+ COVERITY_UNSUPPORTED=1 "$tool_dir/bin/cov-build" --dir "$results_dir" sh -c "ninja -C ./build -v"
+ "$tool_dir/bin/cov-import-scm" --dir "$results_dir" --scm git --log "$results_dir/scm_log.txt"
- if [ "$TAR" = true ]; then
- _pack
- fi
-}
+ tar czf "$results_archive" "$results_dir"
-
-_upload()
-{
- # pack results
- [ -z $PACKED ] || [ $PACKED = false ] && _pack
-
- # Upload results
+ set +x # this is supposed to hide COVERITY_SCAN_TOKEN
echo -e "\033[33;1mUploading Coverity Scan Analysis results...\033[0m"
response=$(curl \
- --silent --write-out "\n%{http_code}\n" \
- --form project=$COVERITY_SCAN_PROJECT_NAME \
- --form token=$COVERITY_SCAN_TOKEN \
- --form email=$COVERITY_SCAN_NOTIFICATION_EMAIL \
- --form file=@$RESULTS_ARCHIVE \
- --form version=$SHA \
- --form description="Travis CI build" \
- $UPLOAD_URL)
+ --silent --write-out "\n%{http_code}\n" \
+ --form project="$COVERITY_SCAN_PROJECT_NAME" \
+ --form token="${COVERITY_SCAN_TOKEN:?}" \
+ --form email="${COVERITY_SCAN_NOTIFICATION_EMAIL:?}" \
+ --form file="@$results_archive" \
+ --form version="$sha" \
+ --form description="Daily build" \
+ https://scan.coverity.com/builds)
printf "\033[33;1mThe response is\033[0m\n%s\n" "$response"
status_code=$(echo "$response" | sed -n '$p')
- # Coverity Scan used to respond with 201 on successfully receiving analysis results.
- # Now for some reason it sends 200 and may change back in the foreseeable future.
- # See https://github.com/pmem/pmdk/commit/7b103fd2dd54b2e5974f71fb65c81ab3713c12c5
if [ "$status_code" != "200" ]; then
- TEXT=$(echo "$response" | sed '$d')
- echo -e "\033[33;1mCoverity Scan upload failed: $TEXT.\033[0m"
- exit 1
+ echo -e "\033[33;1mCoverity Scan upload failed: $(echo "$response" | sed '$d').\033[0m"
+ return 1
fi
-
- echo -e "\n\033[33;1mCoverity Scan Analysis completed successfully.\033[0m"
- exit 0
+ set -x
}
-# PARSE COMMAND LINE OPTIONS
-# --------------------------
-
-case $1 in
- -h|--help)
- _help
- exit 0
- ;;
- build)
- CMD='build'
- TEMP=`getopt -o ho:t --long help,out-dir:,tar -n '$0' -- "$@"`
- _ec=$?
- [[ $_ec -gt 0 ]] && _help && exit $_ec
- shift
- ;;
- upload)
- CMD='upload'
- TEMP=`getopt -o hd:t: --long help,result-dir:tar: -n '$0' -- "$@"`
- _ec=$?
- [[ $_ec -gt 0 ]] && _help && exit $_ec
- shift
- ;;
- *)
- _help && exit 1 ;;
-esac
-
-RESULTS_DIR='cov-int'
-
-eval set -- "$TEMP"
-if [ $? != 0 ] ; then exit 1 ; fi
-
-# extract options and their arguments into variables.
-if [[ $CMD == 'build' ]]; then
- TAR=false
- while true ; do
- case $1 in
- -h|--help)
- _help
- exit 0
- ;;
- -o|--out-dir)
- RESULTS_DIR="$2"
- shift 2
- ;;
- -t|--tar)
- TAR=true
- shift
- ;;
- --) _build; shift ; break ;;
- *) echo "Internal error" ; _help && exit 6 ;;
- esac
- done
-
-elif [[ $CMD == 'upload' ]]; then
- while true ; do
- case $1 in
- -h|--help)
- _help
- exit 0
- ;;
- -d|--result-dir)
- CHANGE_DEFAULT_DIR=true
- RESULTS_DIR="$2"
- shift 2
- ;;
- -t|--tar)
- RESULTS_ARCHIVE="$2"
- [ -z $CHANGE_DEFAULT_DIR ] || [ $CHANGE_DEFAULT_DIR = false ] && PACKED=true
- shift 2
- ;;
- --) _upload; shift ; break ;;
- *) echo "Internal error" ; _help && exit 6 ;;
- esac
- done
-
-fi
+coverity_install_script
+run_coverity
+++ /dev/null
-#!/usr/bin/env bash
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-# Download and extract coverity tool
-
-set -e
-set -o pipefail
-
-# Environment check
-if [ -z "$COVERITY_SCAN_TOKEN" ]; then
- echo >&2 'ERROR: COVERITY_SCAN_TOKEN must be set'
- exit 1
-fi
-
-# Use default values if not set
-PLATFORM="$(uname)"
-TOOL_BASE="${TOOL_BASE:-/tmp/coverity-scan-analysis}"
-TOOL_ARCHIVE="${TOOL_ARCHIVE:-/tmp/cov-analysis-${PLATFORM}.tgz}"
-TOOL_URL="https://scan.coverity.com/download/${PLATFORM}"
-
-# Make sure wget is installed
-sudo apt-get update && sudo apt-get -y install wget
-
-# Get coverity tool
-if [ ! -d "$TOOL_BASE" ]; then
- # Download Coverity Scan Analysis Tool
- if [ ! -e "$TOOL_ARCHIVE" ]; then
- echo -e "\033[33;1mDownloading Coverity Scan Analysis Tool...\033[0m"
- wget -nv -O "$TOOL_ARCHIVE" "$TOOL_URL" --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=$COVERITY_SCAN_TOKEN"
- fi
-
- # Extract Coverity Scan Analysis Tool
- echo -e "\033[33;1mExtracting Coverity Scan Analysis Tool...\033[0m"
- mkdir -p "$TOOL_BASE"
- pushd "$TOOL_BASE"
- tar xzf "$TOOL_ARCHIVE"
- popd
-fi
-
-echo -e "\033[33;1mCoverity Scan Analysis Tool can be found at $TOOL_BASE ...\033[0m"