]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #31779 from keszybz/elf2efi-clang-18
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sat, 23 Mar 2024 11:02:34 +0000 (12:02 +0100)
committerGitHub <noreply@github.com>
Sat, 23 Mar 2024 11:02:34 +0000 (12:02 +0100)
Make elf2efi work with clang-18

307 files changed:
.github/workflows/build_test.yml
.github/workflows/development_freeze.yml
.github/workflows/gather-pr-metadata.yml
.github/workflows/mkosi.yml
.github/workflows/unit_tests.yml
.gitmodules
NEWS
TODO
docs/CONTAINER_INTERFACE.md
docs/CREDENTIALS.md
docs/DAEMON_SOCKET_ACTIVATION.md
docs/ENVIRONMENT.md
docs/HACKING.md
docs/VM_INTERFACE.md [new file with mode: 0644]
docs/WRITING_VM_AND_CONTAINER_MANAGERS.md
docs/_includes/footer.html
hwdb.d/20-usb-vendor-model.hwdb
hwdb.d/60-keyboard.hwdb
hwdb.d/usb.ids
man/common-variables.xml
man/crypttab.xml
man/daemon.xml
man/importctl.xml
man/journalctl.xml
man/org.freedesktop.home1.xml
man/portablectl.xml
man/repart.d.xml
man/rules/meson.build
man/run0.xml [moved from man/uid0.xml with 93% similarity]
man/sd_journal_stream_fd.xml
man/sd_notify.xml
man/systemd-bless-boot.service.xml
man/systemd-boot.xml
man/systemd-bsod.service.xml
man/systemd-cat.xml
man/systemd-cryptsetup.xml
man/systemd-nspawn.xml
man/systemd-pcrlock.xml
man/systemd-poweroff.service.xml
man/systemd-repart.xml
man/systemd-run.xml
man/systemd-soft-reboot.service.xml
man/systemd-storagetm.service.xml
man/systemd-sysext.xml
man/systemd-tpm2-setup.service.xml
man/systemd-vmspawn.xml
man/systemd.dnssd.xml
man/systemd.network.xml
man/systemd.pcrlock.xml
man/systemd.service.xml
man/systemd.socket.xml
man/systemd.special.xml
man/systemd.xml
man/varlinkctl.xml
man/veritytab.xml
meson.build
mkosi.conf
mkosi.images/base/mkosi.conf
mkosi.images/base/mkosi.conf.d/10-arch/mkosi.build.chroot
mkosi.images/base/mkosi.conf.d/10-centos-fedora/mkosi.conf
mkosi.images/base/mkosi.conf.d/10-debian-ubuntu/mkosi.conf
mkosi.images/base/mkosi.conf.d/10-opensuse/initrd/mkosi.postinst
mkosi.images/base/mkosi.conf.d/10-opensuse/mkosi.conf
pkg/arch
pkg/debian
pkg/fedora
pkg/opensuse
po/POTFILES.skip
shell-completion/bash/portablectl
shell-completion/bash/systemd-cat
shell-completion/zsh/_systemd
shell-completion/zsh/_udevadm
src/analyze/analyze-security.c
src/basic/cgroup-util.c
src/basic/chase.c
src/basic/devnum-util.c
src/basic/efivars.c
src/basic/fileio.c
src/basic/format-util.c
src/basic/fs-util.c
src/basic/fs-util.h
src/basic/label.c
src/basic/label.h
src/basic/log.c
src/basic/log.h
src/basic/macro.h
src/basic/missing_audit.h
src/basic/missing_capability.h
src/basic/missing_drm.h
src/basic/missing_fs.h
src/basic/missing_input.h
src/basic/missing_ioprio.h
src/basic/missing_keyctl.h
src/basic/missing_loop.h
src/basic/missing_magic.h
src/basic/missing_mman.h
src/basic/missing_mount.h
src/basic/missing_prctl.h
src/basic/missing_random.h
src/basic/missing_resource.h
src/basic/missing_sched.h
src/basic/missing_timerfd.h
src/basic/missing_type.h
src/basic/missing_wait.h
src/basic/nulstr-util.c
src/basic/nulstr-util.h
src/basic/path-lookup.c
src/basic/path-util.c
src/basic/path-util.h
src/basic/proc-cmdline.c
src/basic/process-util.c
src/basic/socket-util.c
src/basic/stat-util.c
src/basic/stat-util.h
src/basic/string-util.c
src/basic/string-util.h
src/basic/terminal-util.c
src/basic/terminal-util.h
src/basic/time-util.c
src/basic/tmpfile-util.c
src/basic/unit-name.c
src/boot/bless-boot.c
src/boot/efi/efi.h
src/boot/efi/secure-boot.c
src/core/automount.c
src/core/device.c
src/core/exec-invoke.c
src/core/execute.c
src/core/main.c
src/core/manager.c
src/core/manager.h
src/core/mount.c
src/core/path.c
src/core/scope.c
src/core/service.c
src/core/slice.c
src/core/socket.c
src/core/swap.c
src/core/target.c
src/core/timer.c
src/core/unit-printf.c
src/core/unit.c
src/core/unit.h
src/coredump/coredump-vacuum.c
src/fstab-generator/fstab-generator.c
src/home/homed-home-bus.c
src/home/homed-home-bus.h
src/home/homed-home.c
src/home/homed-home.h
src/home/homed-manager-bus.c
src/home/homed-manager.c
src/home/homework-luks.c
src/home/org.freedesktop.home1.conf
src/home/org.freedesktop.home1.policy
src/hostname/hostnamed.c
src/journal/cat.c
src/journal/journalctl.c
src/kernel-install/90-uki-copy.install
src/kernel-install/kernel-install.c
src/libsystemd-network/dhcp-server-internal.h
src/libsystemd-network/dhcp-server-lease-internal.h
src/libsystemd-network/fuzz-dhcp-server.c
src/libsystemd-network/sd-dhcp-server-lease.c
src/libsystemd-network/sd-dhcp-server.c
src/libsystemd/libsystemd.sym
src/libsystemd/sd-device/device-util.c
src/libsystemd/sd-device/device-util.h
src/libsystemd/sd-journal/catalog.c
src/libsystemd/sd-journal/catalog.h
src/libsystemd/sd-journal/journal-send.c
src/libsystemd/sd-journal/journal-send.h
src/libsystemd/sd-journal/sd-journal.c
src/locale/localed-util.c
src/locale/localed.c
src/login/loginctl.c
src/login/logind-dbus.c
src/login/logind-session-device.c
src/machine/machinectl.c
src/network/networkctl.c
src/network/networkd-address.c
src/network/networkd-dhcp-server.c
src/network/networkd-dhcp-server.h
src/network/networkd-link.c
src/network/networkd-manager-varlink.c
src/network/networkd-manager.c
src/network/networkd-manager.h
src/network/networkd-queue.c
src/network/networkd-queue.h
src/network/networkd-route-metric.c
src/network/networkd-route-nexthop.c
src/network/networkd-route.c
src/nspawn/nspawn.c
src/oom/oomd-util.c
src/partition/repart.c
src/portable/portable.c
src/portable/portablectl.c
src/resolve/resolved-conf.c
src/resolve/resolved-conf.h
src/resolve/resolved-dns-query.c
src/resolve/resolved-dns-rr.c
src/resolve/resolved-dns-rr.h
src/resolve/resolved-dns-scope.c
src/resolve/resolved-dns-transaction.c
src/resolve/resolved-dns-transaction.h
src/resolve/resolved-dnssd-bus.c
src/resolve/resolved-dnssd-gperf.gperf
src/resolve/resolved-dnssd.c
src/resolve/resolved-dnssd.h
src/run/meson.build
src/run/run.c
src/run/systemd-run0.in [moved from src/run/systemd-uid0.in with 96% similarity]
src/shared/creds-util.c
src/shared/dissect-image.c
src/shared/dns-domain.c
src/shared/dns-domain.h
src/shared/ethtool-util.c
src/shared/hostname-setup.c
src/shared/install-printf.c
src/shared/install.c
src/shared/install.h
src/shared/json.c
src/shared/json.h
src/shared/kbd-util.c
src/shared/kbd-util.h
src/shared/libcrypt-util.c
src/shared/machine-id-setup.c
src/shared/netif-util.c
src/shared/password-quality-util-pwquality.c
src/shared/pretty-print.c
src/shared/ptyfwd.c
src/shared/specifier.c
src/shared/tests.h
src/shared/varlink.c
src/ssh-generator/ssh-generator.c
src/systemd/meson.build
src/systemd/sd-dhcp-server.h
src/systemd/sd-journal.h
src/test/meson.build
src/test/test-cgroup-util.c
src/test/test-compress.c
src/test/test-dirent-util.c [new file with mode: 0644]
src/test/test-fs-util.c
src/test/test-gpt.c
src/test/test-hashmap.c
src/test/test-hmac.c
src/test/test-install-root.c
src/test/test-label.c [new file with mode: 0644]
src/test/test-mountpoint-util.c
src/test/test-os-util.c
src/test/test-path-util.c
src/test/test-pretty-print.c
src/test/test-recovery-key.c [new file with mode: 0644]
src/test/test-string-util.c
src/test/test-user-util.c
src/tpm2-setup/tpm2-setup.c
src/vmspawn/vmspawn.c
test/TEST-04-JOURNAL/test.sh
test/TEST-74-AUX-UTILS/test.sh
test/meson.build
test/networkd-test.py
test/run-integration-tests.sh
test/test-functions
test/test-systemctl-enable.sh
test/units/testsuite-04.cat.sh [new file with mode: 0755]
test/units/testsuite-04.corrupted-journals.sh
test/units/testsuite-04.journal.sh
test/units/testsuite-46.sh
test/units/testsuite-74.run.sh
tools/dbus_exporter.py
tools/git-setup.sh [moved from tools/add-git-hook.sh with 67% similarity]
units/emergency.service.in
units/meson.build
units/rescue.service.in
units/ssh-access.target [new file with mode: 0644]
units/systemd-battery-check.service.in
units/systemd-bootctl.socket
units/systemd-bootctl@.service [moved from units/systemd-bootctl@.service.in with 88% similarity]
units/systemd-creds.socket
units/systemd-creds@.service
units/systemd-hostnamed.socket
units/systemd-journald.socket
units/systemd-journald@.socket
units/systemd-machine-id-commit.service
units/systemd-modules-load.service.in
units/systemd-networkd.service.in
units/systemd-pcrextend.socket
units/systemd-pcrextend@.service.in
units/systemd-pcrfs-root.service.in
units/systemd-pcrfs@.service.in
units/systemd-pcrlock-file-system.service.in
units/systemd-pcrlock-firmware-code.service.in
units/systemd-pcrlock-firmware-config.service.in
units/systemd-pcrlock-machine-id.service.in
units/systemd-pcrlock-make-policy.service.in
units/systemd-pcrlock-secureboot-authority.service.in
units/systemd-pcrlock-secureboot-policy.service.in
units/systemd-pcrlock.socket
units/systemd-pcrlock@.service.in
units/systemd-pcrmachine.service.in
units/systemd-pcrphase-initrd.service.in
units/systemd-pcrphase-sysinit.service.in
units/systemd-pcrphase.service.in
units/systemd-repart.service [moved from units/systemd-repart.service.in with 96% similarity]
units/systemd-sysext.socket
units/systemd-sysext@.service
units/systemd-tpm2-setup-early.service.in
units/systemd-tpm2-setup.service.in

index 9ef233298003bfb918e384b7dd96410675a9220a..b6476d7045239d4853172836dd0a5cd637b0ae91 100644 (file)
@@ -34,8 +34,5 @@ jobs:
     steps:
       - name: Repository checkout
         uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
-      # FIXME: drop once https://github.com/actions/runner-images/issues/9491  is resolved
-      - name: Reduce ASLR entropy
-        run: sudo sysctl -w vm.mmap_rnd_bits=28
       - name: Build check
         run: .github/workflows/build_test.sh
index ef4f0b50e98ead584f1bd8f0ccc1f11d7e163ad0..f9738d0ffeace1b0b6afa7ad6884958358c97084 100644 (file)
@@ -8,10 +8,6 @@ on:
     types:
       - completed
 
-env:
-  PULL_REQUEST_METADATA_DIR: pull_request
-  PULL_REQUEST_METADATA_FILE: metadata
-
 permissions:
   contents: read
 
@@ -27,40 +23,11 @@ jobs:
       pull-requests: write
 
     steps:
-      - name: Download Pull Request Metadata artifact
-        uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea
-        with:
-          script: |
-            const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
-               owner: context.repo.owner,
-               repo: context.repo.repo,
-               run_id: ${{ github.event.workflow_run.id }},
-            });
-
-            const matchArtifact = artifacts.data.artifacts.filter((artifact) => {
-              return artifact.name == "${{ env.PULL_REQUEST_METADATA_FILE }}"
-            })[0];
-
-            const download = await github.rest.actions.downloadArtifact({
-               owner: context.repo.owner,
-               repo: context.repo.repo,
-               artifact_id: matchArtifact.id,
-               archive_format: 'zip',
-            });
-
-            const fs = require('fs');
-            fs.writeFileSync('${{ github.workspace }}/${{ env.PULL_REQUEST_METADATA_FILE }}.zip', Buffer.from(download.data));
-
-      - run: unzip ${{ env.PULL_REQUEST_METADATA_FILE }}.zip
-
-      - name: 'Get Pull Request number'
-        uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea
+      - id: artifact
+        name: Download Pull Request Metadata artifact
+        uses: redhat-plumbers-in-action/download-artifact@463ae626ac2dd333491c7beccaa24c12c5c259b8
         with:
-          github-token: ${{ secrets.GITHUB_TOKEN }}
-          script: |
-            const fs = require('fs');
-            const pr_number = Number(fs.readFileSync('./${{ env.PULL_REQUEST_METADATA_FILE }}'));
-            core.exportVariable('pr_number', pr_number);
+          name: Pull Request Metadata
 
       - name: Repository checkout
         uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
@@ -68,7 +35,9 @@ jobs:
           fetch-depth: 0
 
       - name: Development Freezer
-        uses: redhat-plumbers-in-action/devel-freezer@67aec4a153bd9fca5322e1c4dd4d7c419fb36362
+        uses: redhat-plumbers-in-action/devel-freezer@396c94ba8cb417474e6626c83a42addea210a403
         with:
-          pr-number: ${{ env.pr_number }}
+          pr-number: ${{ fromJSON(steps.artifact.outputs.pr-metadata-json).number }}
+          # delay start of validation to allow for some milestone/labels tweaking
+          delay: 20
           token: ${{ secrets.GITHUB_TOKEN }}
index 68c88fb94bc07e316c1a3c3b9a9ec29aa23a4612..ae5921aac46f6126407cfc69dfb05e0213191932 100644 (file)
@@ -6,10 +6,6 @@ on:
   pull_request:
     branches: [ main ]
 
-env:
-  PULL_REQUEST_METADATA_DIR: pull_request
-  PULL_REQUEST_METADATA_FILE: metadata
-
 permissions:
   contents: read
 
@@ -21,17 +17,14 @@ jobs:
     steps:
       - name: Repository checkout
         uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
-        with:
-          fetch-depth: 0
 
-      - name: Store PR number in file
-        run: |
-          mkdir -p ./${{ env.PULL_REQUEST_METADATA_DIR }}
-          echo ${{ github.event.number }} >./${{ env.PULL_REQUEST_METADATA_DIR }}/${{ env.PULL_REQUEST_METADATA_FILE }}
+      - id: metadata
+        name: Gather Pull Request Metadata
+        uses: redhat-plumbers-in-action/gather-pull-request-metadata@69c703f376018c1a41c8ccce21dc2e16a79f3324
 
       - name: Upload Pull Request Metadata artifact
         uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3
         with:
-          name: ${{ env.PULL_REQUEST_METADATA_FILE }}
-          path: ${{ env.PULL_REQUEST_METADATA_DIR }}
+          name: Pull Request Metadata
+          path: ${{ steps.metadata.outputs.metadata-file }}
           retention-days: 1
index a71ae3fd39b5ab53ea53543122baf5ea6a130b69..f9df0a22bad0069f8773a4df31251e5c9235019b 100644 (file)
@@ -78,10 +78,14 @@ jobs:
     - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
     - uses: systemd/mkosi@1445b389750af22756c0fde6facc1f2f343340b4
 
+    # Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space
+    # immediately, we remove the files in the background. However, we first move them to a different location
+    # so that nothing tries to use anything in these directories anymore while we're busy deleting them.
     - name: Free disk space
       run: |
-        sudo rm -rf /usr/local
-        sudo rm -rf /opt/hostedtoolcache
+        sudo mv /usr/local /usr/local.trash
+        sudo mv /opt/hostedtoolcache /opt/hostedtoolcache.trash
+        sudo systemd-run rm -rf /usr/local.trash /opt/hostedtoolcache.trash
 
     - name: Configure
       run: |
index 9942df6be2cfe40600895afe9449edc7b4ce0cda..4c398e9eaeb8445b558485d3f49ee2d32474974e 100644 (file)
@@ -31,9 +31,6 @@ jobs:
     steps:
       - name: Repository checkout
         uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
-      # FIXME: drop once https://github.com/actions/runner-images/issues/9491  is resolved
-      - name: Reduce ASLR entropy
-        run: sudo sysctl -w vm.mmap_rnd_bits=28
       - name: Install build dependencies
         run: |
           # Drop XDG_* stuff from /etc/environment, so we don't get the user
index c69576e9bb3c85d7f5e63f5cfe59c703e2e4f6c0..787e4c85f5b68e7e73b9f83f245968b56821cfb1 100644 (file)
@@ -4,11 +4,11 @@
        branch = rawhide
 [submodule "pkg/opensuse"]
        path = pkg/opensuse
-       url = https://code.opensuse.org/package/systemd
-       branch = master
+       url = https://src.opensuse.org/rpm/systemd
+       branch = factory
 [submodule "pkg/debian"]
        path = pkg/debian
-       url = https://salsa.debian.org/systemd-team/systemd
+       url = https://salsa.debian.org/systemd-team/systemd.git
        branch = debian/master
 [submodule "pkg/centos"]
        path = pkg/centos
@@ -16,5 +16,5 @@
        branch = c9s-sig-hyperscale
 [submodule "pkg/arch"]
        path = pkg/arch
-       url = https://gitlab.archlinux.org/daandemeyer/systemd
-       branch = strip
+       url = https://gitlab.archlinux.org/archlinux/packaging/packages/systemd
+       branch = main
diff --git a/NEWS b/NEWS
index 86b7ba77680dc3145e89506123820f163f94e48e..7014e7582af84316544143edf06381ae2ce76d4a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,24 +8,25 @@ CHANGES WITH 256 in spe:
           dropped in a future release.
 
         * Support for cgroup v1 ('legacy' and 'hybrid' hierarchies) is now
-          considered obsolete and systemd by default will refuse to boot under it.
-          To forcibly reenable cgroup v1 support, SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1
-          must be set on kernel command line. The meson option 'default-hierarchy='
-          is also deprecated, i.e. only cgroup v2 ('unified' hierarchy) can be
-          selected as build-time default.
-
-        * Previously, systemd-networkd did not explicitly remove any bridge VLAN
-          IDs assigned on bridge master and ports. Since v256, if a .network
-          file for an interface has at least one valid settings in [BridgeVLAN]
-          section, then all assigned VLAN IDs on the interface that are not
-          configured in the .network file are removed.
+          considered obsolete and systemd by default will refuse to boot under
+          it. To forcibly reenable cgroup v1 support,
+          SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1 must be set on kernel command
+          line. The meson option 'default-hierarchy=' is also deprecated, i.e.
+          only cgroup v2 ('unified' hierarchy) can be selected as build-time
+          default.
+
+        * Previously, systemd-networkd did not explicitly remove any bridge
+          VLAN IDs assigned on bridge master and ports. Since version 256, if a
+          .network file for an interface has at least one valid setting in the
+          [BridgeVLAN] section, then all assigned VLAN IDs on the interface
+          that are not configured in the .network file are removed.
 
         * systemd-gpt-auto-generator will stop generating units for ESP or
           XBOOTLDR partitions if it finds mount entries in the /boot/ or /efi/
           hierarchies in fstab. This is to prevent the generator from
           interfering with systems where ESP is explicitly configured to be
           mounted at some path, for example /boot/efi/ (this type of setup is
-          obsolete but is still commonly found).
+          obsolete but still commonly found).
 
         * The behavior of systemd-sleep and systemd-homed has been updated to
           freeze user sessions when entering the various sleep modes or when
@@ -36,18 +37,442 @@ CHANGES WITH 256 in spe:
           and related services, and SYSTEMD_HOME_LOCK_FREEZE_SESSION=false for
           systemd-homed.service.
 
+        * systemd-tmpfiles and systemd-sysusers, when given a relative path
+          (with at least one directory separator '/'), will open the file
+          directly, instead of searching for the given partial path in the
+          standard locations. The old mode wasn't useful because tmpfiles.d and
+          sysusers.d configuration has a flat structure with no subdirectories
+          under the standard locations and this change makes it easier to work
+          with local files with those tools.
+
+        * systemd-tmpfiles now properly applies nested configuration to 'R' and
+          'D' stanzas. For example, with 'R /foo; x /foo/bar', /foo/bar will
+          now be excluded from removal.
+
+        General Changes and New Features:
+
+        * Various programs will load the main configuration from under
+          /usr/lib/, /usr/local/lib/, and /run/, not just from under /etc/. For
+          example, systemd-logind will look for /etc/systemd/logind.conf,
+          /run/systemd/logind.conf, /usr/local/lib/systemd/logind.conf, and
+          /usr/lib/systemd/logind.conf, and use the first file that is found.
+          This means that the location logic for the main config file and for
+          drop-ins is now the same.
+
+          ukify will look for the config files in /usr/lib/kernel/ and the
+          other locations, and now also supports drop-ins.
+
+          systemd-udevd now supports drop-ins for udev.conf.
+
+        * A new 'systemd-vpick' binary has been added. It implements the new
+          vpick protocol, where a .v directory may contain multiple files with
+          a version, following the UAPI version format specification, embedded
+          in the file name. The files are ordered by version and the newest one
+          is selected.
+
+          systemd-nspawn, systemd-dissect, and the RootDirectory=, RootImage=,
+          ExtensionImages=, and ExtensionDirectories= settings for units now
+          support the vpick protocol and allow the latest version to be
+          selected automatically if a "*.v/" directory is specified as the
+          source.
+
+        * Credentials can now be made accessible to and used by unprivileged
+          users. 'systemd-creds --user --uid=<user>' will encrypt or decrypt a
+          credential for a specific user.
+
+        * With systemd-homed, it is now possible to log in and activate an
+          encrypted home area over SSH.
+
+          homectl is now installed as a multi-call binary. When invoked as
+          systemd-home-fallback-shell it can be used as a temporary shell which
+          allows the home area to interactively unlocked. When the home area
+          becomes available, the temporary shell executes the normal one.
+
+          systemd-homed gained new methods
+          org.freedesktop.home1.Manager.RefHomeUnrestricted,
+          org.freedesktop.home1.Home.RefUnrestricted,
+          org.freedesktop.home1.Manager.ActivateHomeIfReferenced, and
+          org.freedesktop.home1.Home.ActivateIfReferenced to allow logging in
+          without activating the home area and then activating the home area
+          later.
+
+        * JSON User Records have been extended with a separate storage area
+          called "User Record Blob Directories". This is intended to store the
+          user's background image, avatar picture, and other similar items
+          which are too large to fit into the User Record itself.
+
+          systemd-homed, userdbctl, and homectl gained support for blob
+          directories.
+
+        * New command-line tool 'importctl' to download, import, and export
+          disk images via systemd-importd is added with the following verbs:
+          pull-tar, pull-raw, import-tar, import-raw, import-fs, export-tar,
+          export-raw, list-transfers, cancel-transfer.
+
+        Service Manager:
+
+        * New manager setting ProtectSystem= has been added. It is analogous to
+          the unit setting, but applies to the whole system. It is enabled by
+          default in the initrd.
+
+        * New unit setting WantsMountsFor= has been added. It is analogous to
+          RequiresMountsFor=, but with a Wants= dependency instead of
+          Requires=. This new logic is used in various places where mounts were
+          added as dependencies for other settings (WorkingDirectory=-…,
+          PrivateTmp=yes, cryptsetup lines with 'nofail').
+
+        * New unit setting MemoryZSwapWriteback= can be used to control the new
+          memory.zswap.writeback cgroup knob added in kernel 6.8.
+
+        * The manager gained a org.freedesktop.systemd1.StartAuxiliaryScope()
+          method to devolve some processes from a service into a new scope.
+          This new scope will remain even if the original service unit is
+          restarted. Cgroup properties of the new scope are copied from the
+          service, so various limits are retained.
+
+        * Units now expose properties EffectiveMemoryMax=,
+          EffectiveMemoryHigh=, and EffectiveTasksMax=, which report the
+          most stringent limit systemd is aware of for the given unit.
+
+        * A new specifier %D expands to $XDG_DATA_HOME.
+
+        * AllowedCPUs= now supports specifier expansion.
+
+        * What= setting in .mount and .swap units now accepts fstab-style
+          identifiers, for example UUID=… or LABEL=….
+
+        * RestrictNetworkInterfaces= now supports alternative network interface
+          names.
+
+        * PAMName= now implies SetLoginEnvironment=yes.
+
+        * homectl gained a new verb 'firstboot', and a new
+          systemd-homed-firstboot.service unit uses this verb to create users
+          in a first boot environment, either from credentials or by querying
+          interactively.
+
+        * systemd.firstboot=no can be used on the kernel command-line to
+          disable interactive queries, but allow other first boot configuration
+          to happen based on credentials.
+
+        * A new kernel command-line option systemd.default_debug_tty= can be
+          used to specify the TTY for the debug shell, independently of
+          enabling or disabling it.
+
+        * Systemd hostname can be configured via the systemd.hostname
+          credential.
+
+        The Journal:
+
+        * systemd-journald can now forward journal entries to a socket
+          (AF_INET, AF_INET6, AF_UNIX, or AF_VSOCK). The socket can be
+          specified in journald.conf via a new option ForwardAddress= or via
+          the 'journald.forward_address' credential.
+
+        * systemd-journal-remote now also accepts AF_VSOCK and AF_UNIX sockets
+          (so it can be used to receive entries forwarded by systemd-journald).
+
+        * systemd-vmspawn gained a new --forward-journal= option to forward the
+          virtual machine's journal entries to the host. This is done over a
+          AF_VSOCK socket, i.e. it does not require networking in the guest.
+
+        * journalctl gained option '-i' as a shortcut for --file=.
+
+        * journalctl gained a new -T/--exclude-identifier= option to filter
+          out certain syslog identifiers.
+
+        * journalctl gained a new --list-namespaces option.
+
+        * systemd-journal-gatewayd allows restricting the time range of
+          retrieved entries with realtime=[<since>]:[<until>].
+
+        Device Management:
+
+        * Udev now creates symlinks that combine by-path and by-{label,uuid}
+          information:
+            /dev/disk/by-path/<path>/by-<label|uuid|…>/<label|uuid|…>.
+          This allows distinguishing partitions with identical contents on
+          multiple storage devices. This is useful, for example, when copying
+          raw disk contents between devices.
+
+        * Udev now creates persistent /dev/media/by-path symlinks for media
+          controllers. For example, the uvcvideo driver may create /dev/media0
+          which will be linked as
+          /dev/media/by-path/pci-0000:04:00.3-usb-0:1:1.0-media-controller.
+
+        * An allowlist/denylist may be specified to filter which sysfs
+          attributes are used when crafting network interface names. Those
+          lists are stored as HWDB entries
+            ID_NET_NAME_ALLOW_<sysfsattr>=0|1
+          and
+            ID_NET_NAME_ALLOW=0|1.
+          The goal is to avoid unexpected changes to interface names when the
+          kernel is updated and new sysfs attributes become visible.
+
+        * A new unit tpm2.target has been added to provide a synchronization
+          point for units which expect the TPM hardware to be available.
+
+        * systemd-backlight now properly supports numbered devices which the
+          kernel creates to avoid collisions in the leds subsystem.
+
+        * systemd-hwdb update operation can be disabled with environment
+          variable SYSTEMD_HWDB_UPDATE_BYPASS=1.
+
+        * systemd-logind gained a new org.freedesktop.login1.Manager.Sleep()
+          method that automatically redirects to SuspendThenHibernate(),
+          Suspend(), HybridSleep(), or Hibernate(), depending on what is
+          supported and configured, a new configuration setting SleepOperation=,
+          and an accompanying helper method
+          org.freedesktop.login1.Manager.CanSleep() and property
+          org.freedesktop.login1.Manager.SleepOperation.
+
+          'systemctl sleep' calls the new method to automatically put the
+          machine to sleep in the most appropriate way.
+
+        * systemd-hostnamed now exposes the machine ID and boot ID via D-Bus.
+
+        * systemd-hostnamed now provides a Varlink interface.
+
+        * systemd-hostnamed exports the data in os-release(5) and
+          machine-info(5) via D-Bus and Varlink.
+
         Network Management:
 
+        * systemd-networkd now provides a Varlink interface.
+
         * systemd-networkd's proxy support gained a new option to configure
           a private VLAN variant of the proxy ARP supported by the kernel
           under the name IPv4ProxyARPPrivateVLAN=.
 
-        * TPM 1.2 PCR measurement support has been removed from
-          systemd-stub. TPM 1.2 is obsolete and — due to the (by today's
-          standards) weak cryptographic algorithms it only supports — does not
-          actually provide the security benefits it's supposed to
-          provide. Given that the rest of systemd's codebase never supported
-          TPM 1.2 the support has now been removed from systemd-stub as well.
+        * systemd-networkd now exports the NamespaceId and NamespaceNSID
+          properties via D-Bus and Varlink.
+
+        * systemd-networkd now supports IPv6RetransmissionTimeSec= and
+          UseRetransmissionTime= settings in .network files to configure
+          retransmission time for IPv6 neighbor solicitation messages.
+
+        * networkctl gained new verbs 'mask' and 'unmask'.
+
+        * 'networkctl edit --runtime' allows editing volatile configuration
+          under /run/systemd/network/.
+
+        * The implementation behind TTLPropagate= network setting has been
+          removed and the setting is now ignored.
+
+        * systemd-network-generator will now pick up .netdev/.link/.network
+          configuration from credentials.
+
+        * systemd-networkd will now pick up wireguard configuration from
+          credentials.
+
+        * systemd-ssh-proxy is a new SSH client plugin that allows connecting
+          to AF_SOCK or AF_UNIX sockets.
+
+        * systemd-nspawn now provides a /run/systemd/nspawn/unix-export/
+          directory where the container payload can expose AF_UNIX sockets to
+          allow them them to be accessed from outside.
+
+        * systemd-nspawn will tint the background for container output.
+          This can be controller with the new --backgroup= option.
+
+        * systemd-nspawn gained support for the 'owneridmap' option for bind
+          mounts to map the target directory owner from inside the container to
+          the owner of the directory bound from the host filesystem.
+
+        * An sshd config drop-in to allow ssh keys acquired via userdbctl to be
+          used for authorization.
+
+        * New generator systemd-ssh-generator can be used to bind a
+          socket-activated SSH instance to a local AF_SOCK or AF_UNIX socket.
+          This generator will automatically bind /run/host/unix-export/ssh.
+
+        * systemd-resolved now implements RFC 8914 EDE error codes.
+
+        * systemd-resolved and resolvectl now support RFC 9460 SVCB and HTTPS
+          records.
+
+        * resolvectl gained a new option --relax-single-label= to allow
+          querying single-label hostnames via DNS.
+
+        Systemd-boot and systemd-stub and Related Tools:
+
+        * TPM 1.2 PCR measurement support has been removed from systemd-stub.
+          TPM 1.2 is obsolete and – due to the (by today's standards) weak
+          cryptographic algorithms it only supports – does not actually provide
+          the security benefits it's supposed to provide. Given that the rest
+          of systemd's codebase never supported TPM 1.2, the support has now
+          been removed from systemd-stub as well.
+
+        * Confexts are loaded by systemd-stub from the ESP as well.
+
+        * The pcrlock policy is saved in an unencrypted credential file
+          "pcrlock.<entry-token>.cred" under XBOOTLDR/ESP in the
+          /loader/credentials/ directory. It will be picked up at boot by
+          systemd-stub and passed to the initrd, where it can be used to unlock
+          the root file system.
+
+        * kernel-install gained support for --root= for the 'list' verb.
+
+        * systemd-pcrlock gained an --entry-token= option to configure the
+          entry-token.
+
+        * systemd-pcrlock now provides a Varlink interface and can be
+          run as a daemon via a template unit.
+
+        * bootctl now provides a Varlink interface and can be run as a daemon
+          via a template unit.
+
+        * ukify gained support for signing of PCR signatures via OpenSSL's
+          engines and providers.
+
+        * ukify now supports zboot kernels.
+
+        Command-line tools:
+
+        * systemd-run is now a multi-call binary. When invoked as 'run0', it
+          provides as interface similar to 'sudo', with all arguments starting
+          at the first non-option parameter being treated the command to
+          invoke as root. Unlike 'sudo' and similar tools, it does not make use
+          of setuid binaries or other privilege escalation methods, but instead
+          runs the specified command as a transient unit, which is started by
+          the system service manager, so privileges are dropped, rather than
+          gained, thus implementing a much more robust and safe security model.
+
+        * systemd-run gained a new option '--ignore-failure' to suppress
+          command failures.
+
+        * systemd-creds gained new options --user/--uid=.
+
+        * 'systemctl edit --stdin' allows creation of unit files and drop-ins
+          with contents supplied via standard input. This is useful when creating
+          configuration programmatically; the tool takes care of figuring out
+          the file name, creating any directories, and reloading the manager
+          afterwards.
+
+        * 'systemctl disable --now' and 'systemctl mask --now' now work
+          correctly with template units.
+
+        * 'systemd-analyze architectures' lists known CPU architectures.
+
+        * 'systemd-analyze --json=…' is supported for 'architectures',
+          'capability', 'exit-status'.
+
+        * 'systemd-tmpfiles --purge' will purge (remove) all files and
+          directories created via tmpfiles.d configuration.
+
+        * systemd-id128 gained new options --no-pager, --no-legend, and
+          -j/--json=.
+
+        * hostnamectl gained '-j' as shortcut for '--json=pretty' or
+          '--json=short'.
+
+        * loginctl now supports -j/--json=.
+
+        * resolvectl now supports -j/--json= for --type=.
+
+        * systemd-vmspawn gained a new --firmware= option to configure or list
+          firmware definitions for Qemu, a new --tpm= option to enable or
+          disable the use of a software TPM, a new --linux= option to specify a
+          kernel binary for direct kernel boot, a new --initrd= option to
+          specify an initrd for direct kernel boot, a new -D/--directory option
+          to use a plain directory as the root file system, a new
+          --private-users option similar to the one in systemd-nspawn, new
+          options --bind= and --bind-ro= to bind part of the host's file system
+          hierarchy into the guest, a new --extra-drive= option to attach
+          additional storage, and -n/--network-tap/--network-user-mode to
+          configure networking.
+
+        * A new systemd-vmspawn@.service can be used to launch systemd-vmspawn
+          as a service.
+
+        * varlinkctl gained support for the "ssh:" transport. This requires
+          OpenSSH 9.4 or newer.
+
+        * varlinkctl gained a new --collect switch to collect all responses of
+          a method call emitted in JSON_SEQ mode and turn them into normal
+          JSON.
+
+        * systemd-sysext gained support for mutable system extensions, where a
+          writeable upperdir is stored under /var/lib/extensions.mutable/, and
+          a new --mutable option to configure this behaviour.
+
+        * systemd-dissect gained a new --make-archive-option to generate an
+          archive file from a disk image.
+
+        * systemd-repart gained new options --generate-fstab= and
+          --generate-crypttab= to write the fstab and crypttab files.
+
+        * systemd-repart gained a new option --private-key-source= to allow
+          using OpenSSL's "engines" or "providers" as the signing mechanism to
+          use when creating verity signature partitions.
+
+        * systemd-measure gained new options --certificate=, --private-key=,
+          and --private-key-source= to allow using OpenSSL's "engines" or
+          "providers" as the signing mechanism to use when creating signed
+          TPM2 PCR measurement values.
+
+        * systemd-tmpfiles gained a new option --dry-run to print what would be
+          done without actually taking action.
+
+        * systemd-bsod gained a new option --tty= to specify the output TTY
+
+        * timedatectl and machinectl gained option '-P', an alias for
+          '--value --property=…'.
+
+        * Various tools that pretty-print config files will now highlight
+          configuration directives.
+
+        Libraries:
+
+        * libsystemd gained new call sd_bus_creds_new_from_pidfd to get a
+          credentials object for a pidfd and sd_bus_creds_get_pidfd_dup() to
+          retrieve the pidfd from a credentials object.
+
+        * RPM macro %_kernel_install_dir has been added with the path
+          to the directory for kernel-install plugins.
+
+        Other:
+
+        * systemd-logind now supports a new "background-light" session class
+          which does not pull in the user@.service unit. This is intended in
+          particular for cron jobs.
+
+          systemd-logind now also supports a new "user-incomplete" session
+          class for a user session that does not have a running user manager,
+          but may be upgraded to a full "user" session later on. This has
+          been hooked into the PAM stack to appropriately classify sessions
+          while they are being started.
+
+          systemd-logind gained a new org.freedesktop.login1.Session.SetClass()
+          method to change the session class.
+
+          systemd-logind will not allow background, background-light, manager,
+          and manager-early session types to take control of devices or change
+          the session type.
+
+        * systemd-logind gained a new
+          org.freedesktop.login1.Manager.ListSessionsEx() method that provides
+          additional metadata compared to ListSessions(). loginctl makes use of
+          this to list additional fields in list-sessions.
+
+        * systemd-cryptenroll can now enroll directly with a PKCS11 public key
+          (instead of a certificate).
+
+        * Core dumps are now retained for two weeks by default.
+
+        * systemd-cryptsetup gained support for crypttab option
+          link-volume-key= to enter the volume key into the kernel keyring when
+          the volume is opened.
+
+        * portablectl --copy= parameter gained a new 'mixed' argument, that will
+          result in resources owned by the OS (e.g.: portable profiles) to be linked
+          but resources owned by the portable image (e.g.: the unit files and the
+          images themselves) to be copied.
+
+        * The remaining documentation that was on
+          https://freedesktop.org/wiki/Software/systemd/ has been moved to
+          https://systemd.io.
+
 
 CHANGES WITH 255:
 
diff --git a/TODO b/TODO
index 5fd4fdcf69cd9e98059a7267a949c0c997ca6983..96d606ca346684758adebaaa2d786b8b8119ad35 100644 (file)
--- a/TODO
+++ b/TODO
@@ -130,6 +130,11 @@ Deprecations and removals:
 
 Features:
 
+* insert the new pidfs inode number as a third field into PidRef, so that
+  PidRef are reasonably serializable without having to pass around fds.
+
+* systemd-analyze smbios11 to dump smbios type 11 vendor strings
+
 * move documentation about our common env vars (SYSTEMD_LOG_LEVEL,
   SYSTEMD_PAGER, …) into a man page of its own, and just link it from our
   various man pages that so far embed the whole list again and again, in an
@@ -140,11 +145,10 @@ Features:
   speed than SHA256 on 64bit archs (since based on 64bit words unlike SHA256
   which uses 32bit words).
 
-* send out sd_notify() from PID 1 when we determined hostname and machine ID
-
-* send out sd_notify() from PID 1 whenever we reach a target unit. Then
-  introduce ssh.target or so. And in vmspawn/nspawn wait for that as indication
-  whether/when SSH is available. Similar for D-Bus (but just use sockets.target for that)
+* In vmspawn/nspawn/machined wait for X_SYSTEMD_UNIT_ACTIVE=ssh-active.target
+  and X_SYSTEMD_SIGNAL_LEVEL=2 as indication whether/when SSH and the POSIX
+  signals are available. Similar for D-Bus (but just use sockets.target for
+  that). Report as property for the machine.
 
 * teach nspawn/machined a new bus call/verb that gets you a
   shell in containers that have no sensible pid1, via joining the container,
@@ -190,10 +194,6 @@ Features:
   SOURCE_DATE_EPOCH (maybe even under that name?). Would then be used to
   initialize the timestamp logic of ConditionNeedsUpdate=.
 
-* ptyfwd: look for window title ANSI sequences and insert colored dot in front
-  of it while passing it through, to indicate whether we are in privileged, VM,
-  container terminal sessions.
-
 * nspawn/vmspawn/pid1: add ability to easily insert fully booted VMs/FOSC into
   shell pipelines, i.e. add easy to use switch that turns off console status
   output, and generates the right credentials for systemd-run-generator so that
@@ -255,7 +255,7 @@ Features:
 
 * add a new ExecStart= flag that inserts the configured user's shell as first
   word in the command line. (maybe use character '.'). Usecase: tool such as
-  uid0 can use that to spawn the target user's default shell.
+  run0 can use that to spawn the target user's default shell.
 
 * varlink: figure out how to do docs for our varlink interfaces. Idea: install
   interface files augmented with docs in /usr/share/ somewhere. And have
@@ -932,6 +932,8 @@ Features:
   systemd.import_encrypted_creds=foobar.waldo,tmpfiles.extra to protect locked
   down kernels from credentials generated on the host with a weak kernel
 
+* Merge systemd-creds options --uid= (which accepts user names) and --user.
+
 * Add support for extra verity configuration options to systemd-repart (FEC,
   hash type, etc)
 
@@ -1419,6 +1421,9 @@ Features:
 
 * systemd-analyze netif that explains predictable interface (or networkctl)
 
+* Figure out naming of verbs in systemd-analyze: we have (singular) capability,
+  exit-status, but (plural) filesystems, architectures.
+
 * Add service setting to run a service within the specified VRF. i.e. do the
   equivalent of "ip vrf exec".
 
index dcecdecc3eb71d7f8d1d2317ba6cc4b1d1994c33..549dae31fe57bda7f8a4b3706fd8416f40fa674c 100644 (file)
@@ -8,7 +8,7 @@ SPDX-License-Identifier: LGPL-2.1-or-later
 # The Container Interface
 
 Also consult [Writing Virtual Machine or Container
-Managers](https://www.freedesktop.org/wiki/Software/systemd/writing-vm-managers).
+Managers](https://systemd.io/WRITING_VM_AND_CONTAINER_MANAGERS).
 
 systemd has a number of interfaces for interacting with container managers,
 when systemd is used inside of an OS container. If you work on a container
@@ -121,7 +121,7 @@ manager, please consider supporting the following interfaces.
    variable's name you may only specify ptys, and not other types of ttys. Also
    you need to specify the pty itself, a symlink will not suffice. This is
    implemented in
-   [systemd-getty-generator(8)](https://www.freedesktop.org/software/systemd/man/systemd-getty-generator.html).
+   [systemd-getty-generator(8)](https://www.freedesktop.org/software/systemd/man/latest/systemd-getty-generator.html).
    Note that this variable should not include the pty that `/dev/console` maps
    to if it maps to one (see below). Example: if the container receives
    `container_ttys=pts/7 pts/8 pts/14` it will spawn three additional login
@@ -131,7 +131,7 @@ manager, please consider supporting the following interfaces.
    running the container manager, if this is considered desirable, please parse
    the host's `/etc/os-release` and set a `$container_host_<key>=<VALUE>`
    environment variable for the ID fields described by the [os-release
-   interface](https://www.freedesktop.org/software/systemd/man/os-release.html), eg:
+   interface](https://www.freedesktop.org/software/systemd/man/latest/os-release.html), eg:
    `$container_host_id=debian`
    `$container_host_build_id=2020-06-15`
    `$container_host_variant_id=server`
@@ -165,10 +165,15 @@ manager, please consider supporting the following interfaces.
    issuing `journalctl -m`. The container machine ID can be determined from
    `/etc/machine-id` in the container.
 
-3. If the container manager wants to cleanly shutdown the container, it might
+3. If the container manager wants to cleanly shut down the container, it might
    be a good idea to send `SIGRTMIN+3` to its init process. systemd will then
    do a clean shutdown. Note however, that since only systemd understands
-   `SIGRTMIN+3` like this, this might confuse other init systems.
+   `SIGRTMIN+3` like this, this might confuse other init systems. A container
+   manager may implement the `$NOTIFY_SOCKET` protocol mentioned below in which
+   case it will receive a notification message `X_SYSTEMD_SIGNALS_LEVEL=2` that
+   indicates if and when these additional signal handlers are installed. If
+   these signals are sent to the container's PID 1 before this notification
+   message is sent they might not be handled correctly yet.
 
 4. To support [Socket Activated
    Containers](https://0pointer.de/blog/projects/socket-activated-containers.html)
@@ -190,12 +195,14 @@ manager, please consider supporting the following interfaces.
    unit they created for their container. That's private property of systemd,
    and no other code should modify it.
 
-6. systemd running inside the container can report when boot-up is complete
-   using the usual `sd_notify()` protocol that is also used when a service
-   wants to tell the service manager about readiness. A container manager can
-   set the `$NOTIFY_SOCKET` environment variable to a suitable socket path to
-   make use of this functionality. (Also see information about
-   `/run/host/notify` below.)
+6. systemd running inside the container can report when boot-up is complete,
+   boot progress and functionality as well as various other bits of system
+   information using the `sd_notify()` protocol that is also used when a
+   service wants to tell the service manager about readiness. A container
+   manager can set the `$NOTIFY_SOCKET` environment variable to a suitable
+   socket path to make use of this functionality. (Also see information about
+   `/run/host/notify` below, as well as the Readiness Protocol section on
+   [systemd(1)](https://www.freedesktop.org/software/systemd/man/latest/systemd.html)
 
 ## Networking
 
index ed30eacf2bffbfb01dfec800804692e27bbd1257..9c245dbf2b367fb788787719ba642c59ef025364 100644 (file)
@@ -380,7 +380,8 @@ Various services shipped with `systemd` consume credentials for tweaking behavio
   to receive a notification via VSOCK when a virtual machine has finished booting.
   Note that in case the hypervisor does not support `SOCK_DGRAM` over `AF_VSOCK`,
   `SOCK_SEQPACKET` will be tried instead. The credential payload should be in the
-  form: `vsock:<CID>:<PORT>`. Also note that this requires support for VHOST to be
+  form: `vsock:<CID>:<PORT>`. `vsock` may be replaced with `vsock-stream`, `vsock-dgram` or `vsock-seqpacket`
+  to force usage of the corresponding socket type. Also note that this requires support for VHOST to be
   built-in both the guest and the host kernels, and the kernel modules to be loaded.
 
 * [`systemd-sysusers(8)`](https://www.freedesktop.org/software/systemd/man/systemd-sysusers.html)
index 1a027a37c80de2b2585e6eb3b3ca56b7ea08683a..87328ce4cf27c2a2888b2f34f0582b28c30e8e38 100644 (file)
@@ -35,12 +35,14 @@ PrivateNetwork=true
 **/etc/systemd/system/my-nginx.socket**
 
 ```
+[Unit]
+After=network.target
+Requires=network.target
+
 [Socket]
 ListenStream=80
 ListenStream=0.0.0.0:80
 BindIPv6Only=ipv6-only
-After=network.target
-Requires=network.target
 
 [Install]
 WantedBy=sockets.target
index cd6d66a81f1118205c9729d4ba09ec1640507edc..52771226aadd8e01d0e8000b7538b16da8d52578 100644 (file)
@@ -348,12 +348,17 @@ All tools:
   `systemd-gpt-auto-generator` to ensure the root partition is mounted writable
   in accordance to the GPT partition flags.
 
-`systemd-firstboot` and `localectl`:
+`systemd-firstboot`, `localectl`, and `systemd-localed`:
 
 * `$SYSTEMD_LIST_NON_UTF8_LOCALES=1` — if set, non-UTF-8 locales are listed among
   the installed ones. By default non-UTF-8 locales are suppressed from the
   selection, since we are living in the 21st century.
 
+* `$SYSTEMD_KEYMAP_DIRECTORIES=` — takes a colon (`:`) separated list of keymap
+  directories. The directories must be absolute and normalized. If unset, the
+  default keymap directories (/usr/share/keymaps/, /usr/share/kbd/keymaps/, and
+  /usr/lib/kbd/keymaps/) will be used.
+
 `systemd-resolved`:
 
 * `$SYSTEMD_RESOLVED_SYNTHESIZE_HOSTNAME` — if set to "0", `systemd-resolved`
@@ -618,6 +623,13 @@ SYSTEMD_HOME_DEBUG_SUFFIX=foo \
   `nftables`. Selects the firewall backend to use. If not specified tries to
   use `nftables` and falls back to `iptables` if that's not available.
 
+`systemd-networkd`:
+
+* `$SYSTEMD_NETWORK_PERSISTENT_STORAGE_READY` – takes a boolean. If true,
+  systemd-networkd tries to open the persistent storage on start. To make this
+  work, ProtectSystem=strict in systemd-networkd.service needs to be downgraded
+  or disabled.
+
 `systemd-storagetm`:
 
 * `$SYSTEMD_NVME_MODEL`, `$SYSTEMD_NVME_FIRMWARE`, `$SYSTEMD_NVME_SERIAL`,
index 1fbbed91d11d06078345fa6d5819efb03dcc27d8..8abb5e040f21a800b59a66adeaf6b4137b26567e 100644 (file)
@@ -14,6 +14,15 @@ feature, please feel invited to fix it, and submit your work as a
 Please make sure to follow our [Coding Style](CODING_STYLE) when submitting
 patches. Also have a look at our [Contribution Guidelines](CONTRIBUTING).
 
+To start, run the following commands in the systemd git repository to set up
+git correctly (running `meson` will run these commands for you automatically):
+
+```shell
+$ git config submodule.recurse true
+$ git config fetch.recurseSubmodules on-demand
+$ git config push.recurseSubmodules no
+```
+
 When adding new functionality, tests should be added. For shared functionality
 (in `src/basic/` and `src/shared/`) unit tests should be sufficient. The general
 policy is to keep tests in matching files underneath `src/test/`,
diff --git a/docs/VM_INTERFACE.md b/docs/VM_INTERFACE.md
new file mode 100644 (file)
index 0000000..abe7067
--- /dev/null
@@ -0,0 +1,54 @@
+---
+title: VM Interface
+category: Interfaces
+layout: default
+SPDX-License-Identifier: LGPL-2.1-or-later
+---
+
+# The VM Interface
+
+Also consult [Writing Virtual Machine or Container
+Managers](https://systemd.io/WRITING_VM_AND_CONTAINER_MANAGERS).
+
+systemd has a number of interfaces for interacting with virtual machine
+managers, when systemd is used inside of a VM. If you work on a VM manager,
+please consider supporting the following interfaces.
+
+1. systemd supports passing immutable binary data blobs with limited size and
+   restricted access to services via the `ImportCredential=`, `LoadCredential=`
+   and `SetCredential=` settings. These credentials may be passed into a system
+   via SMBIOS Type 11 vendor strings, see
+   [systemd(1)](https://www.freedesktop.org/software/systemd/man/latest/systemd.html)
+   for details. This concept may be used to flexibly configure various facets
+   ot the guest system. See
+   [systemd.system-credentials(7)](https://www.freedesktop.org/software/systemd/man/latest/systemd.system-credentials.html)
+   for a list of system credentials implemented by various systemd components.
+
+2. Readiness, information about various system properties and functionality, as
+   well as progress of boot may be reported by systemd to a machine manager via
+   the `sd_notify()` protocol via `AF_VSOCK` sockets. The address of this
+   socket may be configured via the `vmm.notify_socket` system credential. See
+   [systemd(1)](https://www.freedesktop.org/software/systemd/man/latest/systemd.html).
+
+3. The
+   [systemd-ssh-generator(8)](https://www.freedesktop.org/software/systemd/man/latest/systemd-ssh-generator.html)
+   functionality will automatically bind SSH login functionality to `AF_VSOCK`
+   port 22, if the system runs in a VM.
+
+4. If not initialized yet the system's
+   [machine-id(5)](https://www.freedesktop.org/software/systemd/man/latest/machine-id.html)
+   is automatically set to the SMBIOS product UUID if available and invocation
+   in an VM environment is detected.
+
+5. The
+   [`systemd-boot(7)`](https://www.freedesktop.org/software/systemd/man/latest/systemd-boot.html)
+   and
+   [`systemd-stub(7)`](https://www.freedesktop.org/software/systemd/man/latest/systemd-stub.html)
+   components support two SMBIOS Type 11 vendor strings that may be used to
+   extend the kernel command line of booted Linux environments:
+   `io.systemd.stub.kernel-cmdline-extra=` and
+   `io.systemd.boot.kernel-cmdline-extra=`.
+
+Also see
+[smbios-type-11(7)](https://www.freedesktop.org/software/systemd/man/latest/smbios-type-11.html)
+for a list of supported SMBIOS Type 11 vendor strings.
index 4d1b649df35bc4f8a2074edcc8f5c75730b41a84..272261c5734e653403a74702894fc40cb6c259f4 100644 (file)
@@ -5,25 +5,50 @@ layout: default
 SPDX-License-Identifier: LGPL-2.1-or-later
 ---
 
-
 # Writing VM and Container Managers
 
 _Or: How to hook up your favorite VM or container manager with systemd_
 
-Nomenclature: a _Virtual Machine_ shall refer to a system running on virtualized hardware consisting of a full OS with its own kernel. A _Container_ shall refer to a system running on the same shared kernel of the host, but running a mostly complete OS with its own init system. Both kinds of virtualized systems shall collectively be called "machines".
+Nomenclature: a _Virtual Machine_ shall refer to a system running on
+virtualized hardware consisting of a full OS with its own kernel. A _Container_
+shall refer to a system running on the same shared kernel of the host, but
+running a mostly complete OS with its own init system. Both kinds of
+virtualized systems shall collectively be called "machines".
 
-systemd provides a number of integration points with virtual machine and container managers, such as libvirt, LXC or systemd-nspawn. On one hand there are integration points of the VM/container manager towards the host OS it is running on, and on the other there integration points for container managers towards the guest OS it is managing.
+systemd provides a number of integration points with virtual machine and
+container managers, such as libvirt, LXC or systemd-nspawn. On one hand there
+are integration points of the VM/container manager towards the host OS it is
+running on, and on the other there integration points for container managers
+towards the guest OS it is managing.
 
-Note that this document does not cover lightweight containers for the purpose of application sandboxes, i.e. containers that do _not_ run a init system of their own.
+Note that this document does not cover lightweight containers for the purpose
+of application sandboxes, i.e. containers that do _not_ run a init system of
+their own.
 
 ## Host OS Integration
 
-All virtual machines and containers should be registered with the [machined](http://www.freedesktop.org/wiki/Software/systemd/machined) mini service that is part of systemd. This provides integration into the core OS at various points. For example, tools like ps, cgls, gnome-system-manager use this registration information to show machine information for running processes, as each of the VM's/container's processes can reliably attributed to a registered machine. The various systemd tools (like systemctl, journalctl, loginctl, systemd-run, ...) all support a -M switch that operates on machines registered with machined. "machinectl" may be used to execute operations on any such machine. When a machine is registered via machined its processes will automatically be placed in a systemd scope unit (that is located in the machines.slice slice) and thus appear in "systemctl" and similar commands. The scope unit name is based on the machine meta information passed to machined at registration.
-
-For more details on the APIs provided by machine consult [the bus API interface documentation](http://www.freedesktop.org/wiki/Software/systemd/machined).
+All virtual machines and containers should be registered with the
+[systemd-machined(8)](https://www.freedesktop.org/software/systemd/man/latest/systemd-machined.service.html)
+mini service that is part of systemd. This provides integration into the core
+OS at various points. For example, tools like ps, cgls, gnome-system-manager
+use this registration information to show machine information for running
+processes, as each of the VM's/container's processes can reliably attributed to
+a registered machine. The various systemd tools (like systemctl, journalctl,
+loginctl, systemd-run, ...) all support a -M switch that operates on machines
+registered with machined. "machinectl" may be used to execute operations on any
+such machine. When a machine is registered via machined its processes will
+automatically be placed in a systemd scope unit (that is located in the
+machines.slice slice) and thus appear in "systemctl" and similar commands. The
+scope unit name is based on the machine meta information passed to machined at
+registration.
+
+For more details on the APIs provided by machine consult [the bus API interface
+documentation](https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.machine1.html).
 
 ## Guest OS Integration
 
-As container virtualization is much less comprehensive, and the guest is less isolated from the host, there are a number of interfaces defined how the container manager can set up the environment for systemd running inside a container. These Interfaces are documented in [Container Interface of systemd](http://www.freedesktop.org/wiki/Software/systemd/ContainerInterface).
-
-VM virtualization is more comprehensive and fewer integration APIs are available. In fact there's only one: a VM manager may initialize the SMBIOS DMI field "Product UUUID" to a UUID uniquely identifying this virtual machine instance. This is read in the guest via /sys/class/dmi/id/product_uuid, and used as configuration source for /etc/machine-id if in the guest, if that file is not initialized yet. Note that this is currently only supported for kvm hosts, but may be extended to other managers as well.
+A number of interfaces are defined that permit a machine or container manager
+to set provide integration points with the payload/guest system. These
+interfaces are documented in [Container Interface of
+systemd](https://systemd.io/CONTAINER_INTERFACE) and [VM Interface of
+systemd](https://systemd.io/VM_INTERFACE).
index 3e5214e4839f0091dc82de63e5a5ed8fd181b335..bdaa0eea03c1e53a26f13db560307df07df3f802 100644 (file)
@@ -1,7 +1,7 @@
 <!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
 
 <footer class="site-footer">
-  <p>&copy; systemd, 2023</p>
+  <p>&copy; systemd, 2024</p>
 
   <p><a href="https://github.com/systemd/systemd/tree/main/docs">Website source</a></p>
 </footer>
index d7376b102f0094e3c1a6338c135f274c7ddd0a63..054213c9ba4bbf9258d5531d776acca2932e2517 100644 (file)
@@ -29,6 +29,12 @@ usb:v0011*
 usb:v0011p7788*
  ID_MODEL_FROM_DATABASE=counterfeit flash drive
 
+usb:v001F*
+ ID_VENDOR_FROM_DATABASE=Walmart
+
+usb:v001Fp0B21*
+ ID_MODEL_FROM_DATABASE=AB13X Headset Adapter
+
 usb:v0040*
  ID_VENDOR_FROM_DATABASE=Anyware Corporation
 
@@ -563,6 +569,9 @@ usb:v03F0p0024*
 usb:v03F0p002A*
  ID_MODEL_FROM_DATABASE=LaserJet P1102
 
+usb:v03F0p0036*
+ ID_MODEL_FROM_DATABASE=CCID Smartcard Keyboard KUS0133
+
 usb:v03F0p0053*
  ID_MODEL_FROM_DATABASE=DeskJet 2620 All-in-One Printer
 
@@ -2202,13 +2211,13 @@ usb:v03F3p009B*
  ID_MODEL_FROM_DATABASE=AVC-1410 GameBridge TV NTSC
 
 usb:v03F3p2000*
- ID_MODEL_FROM_DATABASE=USBXchange
+ ID_MODEL_FROM_DATABASE=USBXchange Firmware Loader
 
 usb:v03F3p2001*
  ID_MODEL_FROM_DATABASE=USBXchange Adapter
 
 usb:v03F3p2002*
- ID_MODEL_FROM_DATABASE=USB2-Xchange
+ ID_MODEL_FROM_DATABASE=USB2-Xchange Firmware Loader
 
 usb:v03F3p2003*
  ID_MODEL_FROM_DATABASE=USB2-Xchange Adapter
@@ -2405,6 +2414,15 @@ usb:v0403p6EE0*
 usb:v0403p6F70*
  ID_MODEL_FROM_DATABASE=HB-RF-USB
 
+usb:v0403p7150*
+ ID_MODEL_FROM_DATABASE=FT2232x wired for MPSSE+UART
+
+usb:v0403p7151*
+ ID_MODEL_FROM_DATABASE=FT2232x wired for MPSSE+UART
+
+usb:v0403p7152*
+ ID_MODEL_FROM_DATABASE=FreeCalypso dual UART with boot control
+
 usb:v0403p7BE8*
  ID_MODEL_FROM_DATABASE=FT232R
 
@@ -5090,6 +5108,9 @@ usb:v0424p4041*
 usb:v0424p4060*
  ID_MODEL_FROM_DATABASE=Ultra Fast Media Reader
 
+usb:v0424p4063*
+ ID_MODEL_FROM_DATABASE=xD/SD/MS/MMC Reader
+
 usb:v0424p4064*
  ID_MODEL_FROM_DATABASE=Ultra Fast Media Reader
 
@@ -5858,6 +5879,12 @@ usb:v043Ep9803*
 usb:v043Ep9804*
  ID_MODEL_FROM_DATABASE=DMB Receiver Control
 
+usb:v043Ep9A10*
+ ID_MODEL_FROM_DATABASE=34UC88-B
+
+usb:v043Ep9A11*
+ ID_MODEL_FROM_DATABASE=34UC88-B
+
 usb:v043Ep9A39*
  ID_MODEL_FROM_DATABASE=27UP850 - WK.AEUDCSN - External Monitor 4K
 
@@ -7118,6 +7145,12 @@ usb:v045Ep02EA*
 usb:v045Ep02FD*
  ID_MODEL_FROM_DATABASE=Xbox One S Controller [Bluetooth]
 
+usb:v045Ep02FE*
+ ID_MODEL_FROM_DATABASE=Xbox Wireless Adapter for Windows
+
+usb:v045Ep0306*
+ ID_MODEL_FROM_DATABASE=Surface Pro 7 SD Card Reader
+
 usb:v045Ep0400*
  ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002
 
@@ -7646,6 +7679,9 @@ usb:v045Ep0810*
 usb:v045Ep0823*
  ID_MODEL_FROM_DATABASE=Classic IntelliMouse
 
+usb:v045Ep082A*
+ ID_MODEL_FROM_DATABASE=Pro Intellimouse
+
 usb:v045Ep0900*
  ID_MODEL_FROM_DATABASE=Surface Dock Hub
 
@@ -9339,7 +9375,7 @@ usb:v046DpC52E*
  ID_MODEL_FROM_DATABASE=MK260 Wireless Combo Receiver
 
 usb:v046DpC52F*
- ID_MODEL_FROM_DATABASE=Unifying Receiver
+ ID_MODEL_FROM_DATABASE=Nano Receiver
 
 usb:v046DpC531*
  ID_MODEL_FROM_DATABASE=C-U0007 [Unifying Receiver]
@@ -9348,7 +9384,7 @@ usb:v046DpC532*
  ID_MODEL_FROM_DATABASE=Unifying Receiver
 
 usb:v046DpC534*
- ID_MODEL_FROM_DATABASE=Unifying Receiver
+ ID_MODEL_FROM_DATABASE=Nano Receiver
 
 usb:v046DpC537*
  ID_MODEL_FROM_DATABASE=Cordless Mouse Receiver
@@ -10520,6 +10556,9 @@ usb:v0483p5721*
 usb:v0483p5722*
  ID_MODEL_FROM_DATABASE=Bulk Demo
 
+usb:v0483p572A*
+ ID_MODEL_FROM_DATABASE=STM32F401 microcontroller [ARM Cortex M4] [CDC/ACM serial port]
+
 usb:v0483p5730*
  ID_MODEL_FROM_DATABASE=Audio Speaker
 
@@ -10638,7 +10677,7 @@ usb:v0489pE0CD*
  ID_MODEL_FROM_DATABASE=MediaTek Bluetooth Adapter
 
 usb:v0489pE0D8*
- ID_MODEL_FROM_DATABASE=Bluetooth Adapter
+ ID_MODEL_FROM_DATABASE=Bluetooth 5.2 Adapter [MediaTek MT7922]
 
 usb:v048A*
  ID_VENDOR_FROM_DATABASE=S-MOS Systems, Inc.
@@ -14873,6 +14912,21 @@ usb:v04BFp0321*
 usb:v04BFp0A28*
  ID_MODEL_FROM_DATABASE=INDI AV-IN Device
 
+usb:v04BFp1301*
+ ID_MODEL_FROM_DATABASE=Network Controller
+
+usb:v04BFp1302*
+ ID_MODEL_FROM_DATABASE=i3 Gateway
+
+usb:v04BFp1303*
+ ID_MODEL_FROM_DATABASE=3 Micro Module
+
+usb:v04BFp1304*
+ ID_MODEL_FROM_DATABASE=i3 Module
+
+usb:v04BFp1305*
+ ID_MODEL_FROM_DATABASE=i3 Multi Sensing Module
+
 usb:v04C1*
  ID_VENDOR_FROM_DATABASE=U.S. Robotics (3Com)
 
@@ -15041,6 +15095,9 @@ usb:v04CA*
 usb:v04CAp0020*
  ID_MODEL_FROM_DATABASE=USB Keyboard
 
+usb:v04CAp003A*
+ ID_MODEL_FROM_DATABASE=Multimedia Keyboard
+
 usb:v04CAp004B*
  ID_MODEL_FROM_DATABASE=Keyboard
 
@@ -15707,6 +15764,9 @@ usb:v04D9p1503*
 usb:v04D9p1603*
  ID_MODEL_FROM_DATABASE=Keyboard
 
+usb:v04D9p1605*
+ ID_MODEL_FROM_DATABASE=Keyboard
+
 usb:v04D9p1702*
  ID_MODEL_FROM_DATABASE=Keyboard LKS02
 
@@ -17486,6 +17546,9 @@ usb:v04F2pB71A*
 usb:v04F2pB76B*
  ID_MODEL_FROM_DATABASE=SunplusIT Inc [HP HD Camera]
 
+usb:v04F2pB7B4*
+ ID_MODEL_FROM_DATABASE=Integrated Camera (1920x1080)
+
 usb:v04F3*
  ID_VENDOR_FROM_DATABASE=Elan Microelectronics Corp.
 
@@ -19355,6 +19418,12 @@ usb:v04FE*
 usb:v04FEp0006*
  ID_MODEL_FROM_DATABASE=Happy Hacking Keyboard Lite2
 
+usb:v04FEp0020*
+ ID_MODEL_FROM_DATABASE=HHKB-Classic
+
+usb:v04FEp0021*
+ ID_MODEL_FROM_DATABASE=Happy Hacking Keyboard Professional HYBRID Type-S
+
 usb:v04FF*
  ID_VENDOR_FROM_DATABASE=E-CMOS Corp.
 
@@ -19556,6 +19625,9 @@ usb:v050Dp0083*
 usb:v050Dp0084*
  ID_MODEL_FROM_DATABASE=F8T003v2 Bluetooth
 
+usb:v050Dp008A*
+ ID_MODEL_FROM_DATABASE=6-in-1 Multiport Adapter
+
 usb:v050Dp0102*
  ID_MODEL_FROM_DATABASE=Flip KVM
 
@@ -20987,6 +21059,9 @@ usb:v054Cp0643*
 usb:v054Cp0689*
  ID_MODEL_FROM_DATABASE=Walkman NWZ-B173F
 
+usb:v054Cp068C*
+ ID_MODEL_FROM_DATABASE=UP-D711
+
 usb:v054Cp06BB*
  ID_MODEL_FROM_DATABASE=WALKMAN NWZ-F805
 
@@ -22151,18 +22226,39 @@ usb:v056Ap03B2*
 usb:v056Ap03B3*
  ID_MODEL_FROM_DATABASE=DTH167 [Cintiq Pro 16] touchscreen
 
+usb:v056Ap03C0*
+ ID_MODEL_FROM_DATABASE=DTH271 [Cintiq Pro 27] touchscreen
+
+usb:v056Ap03C4*
+ ID_MODEL_FROM_DATABASE=DTH172 [Cintiq Pro 17]
+
 usb:v056Ap03C5*
  ID_MODEL_FROM_DATABASE=CTL-4100WL [Intuos BT (S)]
 
 usb:v056Ap03C7*
  ID_MODEL_FROM_DATABASE=CTL-6100WL [Intuos BT (M)]
 
+usb:v056Ap03CB*
+ ID_MODEL_FROM_DATABASE=DTH134 [Wacom One 13] touchscreen
+
+usb:v056Ap03CE*
+ ID_MODEL_FROM_DATABASE=DTC121 [Wacom One 12] touchscreen
+
+usb:v056Ap03D0*
+ ID_MODEL_FROM_DATABASE=DTH227 [Cintiq Pro 22]
+
 usb:v056Ap03DC*
  ID_MODEL_FROM_DATABASE=PTH-460 [Intuos Pro (S)] tablet
 
 usb:v056Ap03DD*
  ID_MODEL_FROM_DATABASE=PTH-460 [Intuos Pro BT (S)] tablet
 
+usb:v056Ap03EC*
+ ID_MODEL_FROM_DATABASE=DTH134 [DTH134] touchscreen
+
+usb:v056Ap03ED*
+ ID_MODEL_FROM_DATABASE=DTC121 [DTC121] touchscreen
+
 usb:v056Ap0400*
  ID_MODEL_FROM_DATABASE=PenPartner 4x5
 
@@ -22221,10 +22317,10 @@ usb:v056Dp4000*
  ID_MODEL_FROM_DATABASE=FlexScan EV3237
 
 usb:v056Dp4001*
- ID_MODEL_FROM_DATABASE=Monitor
+ ID_MODEL_FROM_DATABASE=FlexScan EV2450
 
 usb:v056Dp4002*
- ID_MODEL_FROM_DATABASE=USB HID Monitor
+ ID_MODEL_FROM_DATABASE=FlexScan EV2455
 
 usb:v056Dp4014*
  ID_MODEL_FROM_DATABASE=FlexScan EV2750
@@ -22235,6 +22331,9 @@ usb:v056Dp4026*
 usb:v056Dp4027*
  ID_MODEL_FROM_DATABASE=FlexScan EV2456
 
+usb:v056Dp402B*
+ ID_MODEL_FROM_DATABASE=FlexScan EV2780
+
 usb:v056Dp4036*
  ID_MODEL_FROM_DATABASE=FlexScan EV2785
 
@@ -22253,12 +22352,18 @@ usb:v056Dp405A*
 usb:v056Dp405B*
  ID_MODEL_FROM_DATABASE=FlexScan EV2460
 
+usb:v056Dp405E*
+ ID_MODEL_FROM_DATABASE=FlexScan EV2495
+
 usb:v056Dp405F*
  ID_MODEL_FROM_DATABASE=FlexScan EV2795
 
 usb:v056Dp4065*
  ID_MODEL_FROM_DATABASE=FlexScan EV3895
 
+usb:v056Dp406A*
+ ID_MODEL_FROM_DATABASE=FlexScan EV2480
+
 usb:v056E*
  ID_VENDOR_FROM_DATABASE=Elecom Co., Ltd
 
@@ -24575,6 +24680,9 @@ usb:v059Fp1094*
 usb:v059Fp1095*
  ID_MODEL_FROM_DATABASE=Rugged
 
+usb:v059Fp1105*
+ ID_MODEL_FROM_DATABASE=Mobile Drive (RLSD: 2022)
+
 usb:v059FpA601*
  ID_MODEL_FROM_DATABASE=HardDrive
 
@@ -27026,6 +27134,9 @@ usb:v05E5*
 usb:v05E6*
  ID_VENDOR_FROM_DATABASE=Keithley Instruments
 
+usb:v05E6p3390*
+ ID_MODEL_FROM_DATABASE=3390 Arbitrary Waveform Generator
+
 usb:v05E8*
  ID_VENDOR_FROM_DATABASE=ICC, Inc.
 
@@ -27689,6 +27800,12 @@ usb:v0638p4004*
 usb:v0639*
  ID_VENDOR_FROM_DATABASE=Chrontel, Inc.
 
+usb:v0639p7213*
+ ID_MODEL_FROM_DATABASE=CH7213
+
+usb:v0639p7231*
+ ID_MODEL_FROM_DATABASE=CH7213
+
 usb:v063A*
  ID_VENDOR_FROM_DATABASE=Techwin Corp.
 
@@ -29897,6 +30014,9 @@ usb:v06CBp00C7*
 usb:v06CBp00CB*
  ID_MODEL_FROM_DATABASE=Fingerprint scanner
 
+usb:v06CBp00FC*
+ ID_MODEL_FROM_DATABASE=Prometheus Fingerprint Reader
+
 usb:v06CBp0AC3*
  ID_MODEL_FROM_DATABASE=Large Touch Screen
 
@@ -30080,9 +30200,15 @@ usb:v06D3p0393*
 usb:v06D3p0394*
  ID_MODEL_FROM_DATABASE=CP9000D/DW Port
 
+usb:v06D3p0395*
+ ID_MODEL_FROM_DATABASE=CP9000DW
+
 usb:v06D3p0398*
  ID_MODEL_FROM_DATABASE=P93D
 
+usb:v06D3p039E*
+ ID_MODEL_FROM_DATABASE=CP9500DW-S
+
 usb:v06D3p03A1*
  ID_MODEL_FROM_DATABASE=CP9550D/DW Port
 
@@ -30110,9 +30236,15 @@ usb:v06D3p0F10*
 usb:v06D3p3B10*
  ID_MODEL_FROM_DATABASE=P95D
 
+usb:v06D3p3B20*
+ ID_MODEL_FROM_DATABASE=CP9820DW Series
+
 usb:v06D3p3B21*
  ID_MODEL_FROM_DATABASE=CP-9810D/DW
 
+usb:v06D3p3B2F*
+ ID_MODEL_FROM_DATABASE=LS9820A
+
 usb:v06D3p3B30*
  ID_MODEL_FROM_DATABASE=CP-D70DW / CP-D707DW
 
@@ -33551,6 +33683,9 @@ usb:v07CEpC009*
 usb:v07CEpC010*
  ID_MODEL_FROM_DATABASE=CPB-7000
 
+usb:v07CEpC011*
+ ID_MODEL_FROM_DATABASE=ASK-2500
+
 usb:v07CF*
  ID_VENDOR_FROM_DATABASE=Casio Computer Co., Ltd
 
@@ -33957,11 +34092,20 @@ usb:v07FDp0002*
  ID_MODEL_FROM_DATABASE=MOTU Audio for 64 bit
 
 usb:v07FDp0004*
- ID_MODEL_FROM_DATABASE=MicroBook
+ ID_MODEL_FROM_DATABASE=Microbook I/II/IIc
 
 usb:v07FDp0008*
  ID_MODEL_FROM_DATABASE=M Series
 
+usb:v07FDp0009*
+ ID_MODEL_FROM_DATABASE=M Series (firmware update mode)
+
+usb:v07FDp000B*
+ ID_MODEL_FROM_DATABASE=M Series
+
+usb:v07FDp000D*
+ ID_MODEL_FROM_DATABASE=M Series (firmware update mode)
+
 usb:v07FF*
  ID_VENDOR_FROM_DATABASE=Unknown
 
@@ -34142,6 +34286,9 @@ usb:v0827*
 usb:v0828*
  ID_VENDOR_FROM_DATABASE=Sato Corp.
 
+usb:v0828pA003*
+ ID_MODEL_FROM_DATABASE=WS408 Label Printer
+
 usb:v0829*
  ID_VENDOR_FROM_DATABASE=DirecTV Broadband, Inc. (Telocity)
 
@@ -36056,6 +36203,24 @@ usb:v0908p04B3*
 usb:v0908p04B4*
  ID_MODEL_FROM_DATABASE=SCR_CCID
 
+usb:v0908p04B5*
+ ID_MODEL_FROM_DATABASE=Camera
+
+usb:v0908p04B6*
+ ID_MODEL_FROM_DATABASE=Cockpit Touchkeypad
+
+usb:v0908p04B7*
+ ID_MODEL_FROM_DATABASE=Cockpit Touchkeypad Bootloader
+
+usb:v0908p04B8*
+ ID_MODEL_FROM_DATABASE=MediSET USB4-W
+
+usb:v0908p04B9*
+ ID_MODEL_FROM_DATABASE=MediSET USB4-R
+
+usb:v0908p04BA*
+ ID_MODEL_FROM_DATABASE=MediSET USB4-G
+
 usb:v0908p2701*
  ID_MODEL_FROM_DATABASE=ShenZhen SANZHAI Technology Co.,Ltd Spy Pen VGA
 
@@ -36110,6 +36275,9 @@ usb:v090Cp1000*
 usb:v090Cp1132*
  ID_MODEL_FROM_DATABASE=5-in-1 Card Reader
 
+usb:v090Cp2000*
+ ID_MODEL_FROM_DATABASE=Disk
+
 usb:v090Cp337B*
  ID_MODEL_FROM_DATABASE=Silicon Motion Camera
 
@@ -36374,6 +36542,9 @@ usb:v091Ep4CDB*
 usb:v0920*
  ID_VENDOR_FROM_DATABASE=Echelon Co.
 
+usb:v0920p5550*
+ ID_MODEL_FROM_DATABASE=U60 FT Network Interface
+
 usb:v0920p7500*
  ID_MODEL_FROM_DATABASE=Network Interface
 
@@ -37028,6 +37199,9 @@ usb:v0944p0117*
 usb:v0944p012F*
  ID_MODEL_FROM_DATABASE=SQ-1
 
+usb:v0944p0203*
+ ID_MODEL_FROM_DATABASE=KRONOS
+
 usb:v0944p0F03*
  ID_MODEL_FROM_DATABASE=K-Series K61P MIDI studio controller
 
@@ -37241,6 +37415,12 @@ usb:v0955p7210*
 usb:v0955p7321*
  ID_MODEL_FROM_DATABASE=Switch [Tegra Erista] recovery mode
 
+usb:v0955p7323*
+ ID_MODEL_FROM_DATABASE=T234 [Orin NX 16GB] recovery mode
+
+usb:v0955p7423*
+ ID_MODEL_FROM_DATABASE=T234 [Orin NX 8GB] recovery mode
+
 usb:v0955p7721*
  ID_MODEL_FROM_DATABASE=T210 [TX1 Tegra Erista] recovery mode
 
@@ -37277,6 +37457,12 @@ usb:v0956*
 usb:v0957*
  ID_VENDOR_FROM_DATABASE=Agilent Technologies, Inc.
 
+usb:v0957p0007*
+ ID_MODEL_FROM_DATABASE=82357A GPIB Interface Firmware loader
+
+usb:v0957p0107*
+ ID_MODEL_FROM_DATABASE=82357A GPIB Interface
+
 usb:v0957p0200*
  ID_MODEL_FROM_DATABASE=E-Video DC-350 Camera
 
@@ -37287,6 +37473,12 @@ usb:v0957p0407*
  ID_MODEL_FROM_DATABASE=33220A Waveform Generator
 
 usb:v0957p0518*
+ ID_MODEL_FROM_DATABASE=82357B GPIB Interface Firmware loader
+
+usb:v0957p0607*
+ ID_MODEL_FROM_DATABASE=34410A Multimeter
+
+usb:v0957p0718*
  ID_MODEL_FROM_DATABASE=82357B GPIB Interface
 
 usb:v0957p0A07*
@@ -37298,6 +37490,9 @@ usb:v0957p1507*
 usb:v0957p1745*
  ID_MODEL_FROM_DATABASE=Test and Measurement Device (IVI)
 
+usb:v0957p1907*
+ ID_MODEL_FROM_DATABASE=53230A Frequency Counter
+
 usb:v0957p1F01*
  ID_MODEL_FROM_DATABASE=N5181A MXG Analog Signal Generator
 
@@ -37547,6 +37742,9 @@ usb:v099Ap713A*
 usb:v099Ap7160*
  ID_MODEL_FROM_DATABASE=Hyper Slim Keyboard
 
+usb:v099Ap7202*
+ ID_MODEL_FROM_DATABASE=Enermax Aurora Micro Wireless Receiver
+
 usb:v099E*
  ID_VENDOR_FROM_DATABASE=Trimble Navigation, Ltd
 
@@ -37823,6 +38021,12 @@ usb:v09D8p0320*
 usb:v09D8p0406*
  ID_MODEL_FROM_DATABASE=TWN4 MIFARE NFC
 
+usb:v09D8p0410*
+ ID_MODEL_FROM_DATABASE=TWN4 HID
+
+usb:v09D8p0420*
+ ID_MODEL_FROM_DATABASE=TWN4 CDC
+
 usb:v09D9*
  ID_VENDOR_FROM_DATABASE=KRF Tech, Ltd
 
@@ -37847,6 +38051,9 @@ usb:v09DAp001A*
 usb:v09DAp002A*
  ID_MODEL_FROM_DATABASE=Wireless Optical Mouse NB-30
 
+usb:v09DAp0103*
+ ID_MODEL_FROM_DATABASE=Oscar X-710BK Gaming Mouse
+
 usb:v09DAp022B*
  ID_MODEL_FROM_DATABASE=Wireless Mouse (Battery Free)
 
@@ -37868,6 +38075,12 @@ usb:v09DAp1068*
 usb:v09DAp112C*
  ID_MODEL_FROM_DATABASE=Bloody V5 Mouse
 
+usb:v09DAp2268*
+ ID_MODEL_FROM_DATABASE=Keyboard (FK11)
+
+usb:v09DAp2690*
+ ID_MODEL_FROM_DATABASE=PK-635G
+
 usb:v09DAp3A60*
  ID_MODEL_FROM_DATABASE=Bloody V8M Core 2 Mouse
 
@@ -37881,11 +38094,17 @@ usb:v09DAp9066*
  ID_MODEL_FROM_DATABASE=F3 V-Track Gaming Mouse
 
 usb:v09DAp9090*
- ID_MODEL_FROM_DATABASE=XL-730K / XL-750BK / XL-755BK Mice
+ ID_MODEL_FROM_DATABASE=XL-730K / XL-747H / XL-750BK / XL-755BK Mice
 
 usb:v09DApF613*
  ID_MODEL_FROM_DATABASE=Bloody V7M Mouse
 
+usb:v09DApF6CC*
+ ID_MODEL_FROM_DATABASE=B314 Light Strike Gaming Keyboard
+
+usb:v09DApFA44*
+ ID_MODEL_FROM_DATABASE=B930 Light Strike RGB Mechanical Gaming Keyboard
+
 usb:v09DB*
  ID_VENDOR_FROM_DATABASE=Measurement Computing Corp.
 
@@ -37934,6 +38153,9 @@ usb:v09E7*
 usb:v09E8*
  ID_VENDOR_FROM_DATABASE=AKAI  Professional M.I. Corp.
 
+usb:v09E8p0029*
+ ID_MODEL_FROM_DATABASE=APC40 mkII
+
 usb:v09E8p0045*
  ID_MODEL_FROM_DATABASE=MPK Mini Mk II MIDI Controller
 
@@ -37949,6 +38171,9 @@ usb:v09E8p0071*
 usb:v09E8p0076*
  ID_MODEL_FROM_DATABASE=LPK25 MIDI Keyboard
 
+usb:v09E8p007C*
+ ID_MODEL_FROM_DATABASE=MPK Mini MIDI Controller
+
 usb:v09E9*
  ID_VENDOR_FROM_DATABASE=Chen-Source, Inc.
 
@@ -38138,6 +38363,15 @@ usb:v0A12p1011*
 usb:v0A12p1012*
  ID_MODEL_FROM_DATABASE=Bluetooth Device
 
+usb:v0A12p1243*
+ ID_MODEL_FROM_DATABASE=CSRA64210 [TaoTronics Headset BH-22 in charging mode]
+
+usb:v0A12p4007*
+ ID_MODEL_FROM_DATABASE=Mpow HC5 Headset in charging mode - HID / Mass Storage
+
+usb:v0A12p4010*
+ ID_MODEL_FROM_DATABASE=Mpow HC5 Headset in charging mode - USB Hub
+
 usb:v0A12pFFFF*
  ID_MODEL_FROM_DATABASE=USB Bluetooth Device in DFU State
 
@@ -38267,6 +38501,9 @@ usb:v0A35p002A*
 usb:v0A35p008A*
  ID_MODEL_FROM_DATABASE=SAC Hub
 
+usb:v0A38*
+ ID_VENDOR_FROM_DATABASE=IRIS sa
+
 usb:v0A39*
  ID_VENDOR_FROM_DATABASE=Gilat Satellite Networks, Ltd
 
@@ -38639,6 +38876,9 @@ usb:v0A5Cp2198*
 usb:v0A5Cp219B*
  ID_MODEL_FROM_DATABASE=Bluetooth 2.1 Device
 
+usb:v0A5Cp219C*
+ ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth
+
 usb:v0A5Cp21B1*
  ID_MODEL_FROM_DATABASE=HP Bluetooth Module
 
@@ -38708,6 +38948,9 @@ usb:v0A5Cp5803*
 usb:v0A5Cp5804*
  ID_MODEL_FROM_DATABASE=BCM5880 Secure Applications Processor with fingerprint swipe sensor
 
+usb:v0A5Cp5832*
+ ID_MODEL_FROM_DATABASE=BCM5880 Secure Applications Processor Smartcard reader
+
 usb:v0A5Cp6300*
  ID_MODEL_FROM_DATABASE=Pirelli Remote NDIS Device
 
@@ -64115,6 +64358,12 @@ usb:v20A0p0006*
 usb:v20A0p4107*
  ID_MODEL_FROM_DATABASE=GPF Crypto Stick V1.2
 
+usb:v20A0p4108*
+ ID_MODEL_FROM_DATABASE=Nitrokey Pro
+
+usb:v20A0p4109*
+ ID_MODEL_FROM_DATABASE=Nitrokey Storage
+
 usb:v20A0p4123*
  ID_MODEL_FROM_DATABASE=IKALOGIC SCANALOGIC 2
 
@@ -64139,9 +64388,36 @@ usb:v20A0p4211*
 usb:v20A0p4223*
  ID_MODEL_FROM_DATABASE=ATSAMD21 [castAR]
 
+usb:v20A0p4230*
+ ID_MODEL_FROM_DATABASE=Nitrokey HSM
+
+usb:v20A0p4287*
+ ID_MODEL_FROM_DATABASE=Nitrokey FIDO U2F
+
 usb:v20A0p428D*
  ID_MODEL_FROM_DATABASE=Electrosense wideband converter
 
+usb:v20A0p42B1*
+ ID_MODEL_FROM_DATABASE=Nitrokey FIDO2
+
+usb:v20A0p42B2*
+ ID_MODEL_FROM_DATABASE=Nitrokey 3A Mini/3A NFC/3C NFC
+
+usb:v20A0p42B4*
+ ID_MODEL_FROM_DATABASE=Nitrokey Pro Bootloader
+
+usb:v20A0p42DA*
+ ID_MODEL_FROM_DATABASE=MuteMe
+
+usb:v20A0p42DD*
+ ID_MODEL_FROM_DATABASE=Nitrokey 3A NFC Bootloader/3C NFC Bootloader
+
+usb:v20A0p42E8*
+ ID_MODEL_FROM_DATABASE=Nitrokey 3A Mini Bootloader
+
+usb:v20A0p42EC*
+ ID_MODEL_FROM_DATABASE=RP2040 [PicoWifi]
+
 usb:v20B1*
  ID_VENDOR_FROM_DATABASE=XMOS Ltd
 
@@ -66303,7 +66579,7 @@ usb:v2581p1808*
  ID_MODEL_FROM_DATABASE=WinUSB Smartcard
 
 usb:v2581pF1D0*
- ID_MODEL_FROM_DATABASE=FIDO U2F Security Key
+ ID_MODEL_FROM_DATABASE=Nitrokey U2F
 
 usb:v258D*
  ID_VENDOR_FROM_DATABASE=Sequans Communications
index 8a0693cf0d4db97b65b430222031cc058dae317d..06411bf6204b390260e2c9785c3efffbf267c2fd 100644 (file)
@@ -2086,6 +2086,11 @@ evdev:name:AT Translated Set 2 keyboard:dmi:bvn*:svnPositivoTecnologiaSA:pn*:pvr
 evdev:name:AT Translated Set 2 keyboard:dmi:bvn*:svnPositivoTecnologiaSA:pn*:pvr*:rvnPositivoTecnologiaSA:rnK116*
  KEYBOARD_KEY_76=f21                                    # Fn+F1 toggle touchpad
 
+# Positivo (N14NPE-N, N15NPE-N)
+evdev:name:AT Translated Set 2 keyboard:dmi:bvn*:svnPositivo*:pn*:pvr*:rvnPositivo*:rnN1[45]NPE-N*
+ KEYBOARD_KEY_76=f21                                    # Fn+F1 toggle touchpad
+ KEYBOARD_KEY_dd=search
+
 # Positivo (CG15D)
 evdev:name:AT Translated Set 2 keyboard:dmi:bvn*:bvr*:svnPositivoTecnologiaSA:pn*:pvr*:rvn*:rnCG15D*
 # Positivo Motion (N14DP6, N14DP7, N14DP7-V2, N14DP9, N14JP6, N14KP6)
index 631c1bcbf60011621eeabc2e27b97f1ddbe30c85..a1e3ea4acd1d7fca174c298f475daa1c32fec832 100644 (file)
@@ -9,8 +9,8 @@
 #      The latest version can be obtained from
 #              http://www.linux-usb.org/usb.ids
 #
-# Version: 2023.11.08
-# Date:    2023-11-08 20:34:02
+# Version: 2024.03.18
+# Date:    2024-03-18 20:34:02
 #
 
 # Vendors, devices and interfaces. Please keep sorted.
@@ -29,6 +29,8 @@
 0004  Nebraska Furniture Mart
 0011  Unknown
        7788  counterfeit flash drive
+001f  Walmart
+       0b21  AB13X Headset Adapter
 0040  Anyware Corporation
        073d  Mini Multimedia 2.4GHz Wireless Keyboard with Touch Pad
 0042  DMT
        0012  DeskJet 1125C Printer Port
        0024  KU-0316 Keyboard
        002a  LaserJet P1102
+       0036  CCID Smartcard Keyboard KUS0133
        0053  DeskJet 2620 All-in-One Printer
        0101  ScanJet 4100c
        0102  PhotoSmart S20
        008c  AVC-2310 Device
        0094  eHome Infrared Receiver
        009b  AVC-1410 GameBridge TV NTSC
-       2000  USBXchange
+       2000  USBXchange Firmware Loader
        2001  USBXchange Adapter
-       2002  USB2-Xchange
+       2002  USB2-Xchange Firmware Loader
        2003  USB2-Xchange Adapter
        4000  4-port hub
        adcc  Composite Device Support
        601f  FT601 32-bit FIFO IC
        6ee0  EZO Carrier Board
        6f70  HB-RF-USB
+       7150  FT2232x wired for MPSSE+UART
+       7151  FT2232x wired for MPSSE+UART
+       7152  FreeCalypso dual UART with boot control
        7be8  FT232R
        8028  Dev board JTAG (FT232H based)
        8040  4 Port Hub
        3fcc  RME MADIface
        4041  Hub and media card controller
        4060  Ultra Fast Media Reader
+       4063  xD/SD/MS/MMC Reader
        4064  Ultra Fast Media Reader
        4712  USB4712 high-speed hub
        4713  USB4715 high-speed hub (2 ports disabled)
        9800  Remote Control Receiver_iMON
        9803  eHome Infrared Receiver
        9804  DMB Receiver Control
+       9a10  34UC88-B
+       9a11  34UC88-B
        9a39  27UP850 - WK.AEUDCSN - External Monitor 4K
        9c01  LGE Sync
 043f  RadiSys Corp.
        02e6  Xbox Wireless Adapter for Windows
        02ea  Xbox One Controller
        02fd  Xbox One S Controller [Bluetooth]
+       02fe  Xbox Wireless Adapter for Windows
+       0306  Surface Pro 7 SD Card Reader
        0400  Windows Powered Pocket PC 2002
        0401  Windows Powered Pocket PC 2002
        0402  Windows Powered Pocket PC 2002
        0800  Wireless keyboard (All-in-One-Media)
        0810  LifeCam HD-3000
        0823  Classic IntelliMouse
+       082a  Pro Intellimouse
        0900  Surface Dock Hub
        0901  Surface Dock Hub
        0902  Surface Dock Hub
        c52b  Unifying Receiver
        c52d  R700 Remote Presenter receiver
        c52e  MK260 Wireless Combo Receiver
-       c52f  Unifying Receiver
+       c52f  Nano Receiver
        c531  C-U0007 [Unifying Receiver]
        c532  Unifying Receiver
-       c534  Unifying Receiver
+       c534  Nano Receiver
        c537  Cordless Mouse Receiver
        c539  Lightspeed Receiver
        c53a  PowerPlay Wireless Charging System
        5720  Mass Storage Device
        5721  Interrupt Demo
        5722  Bulk Demo
+       572a  STM32F401 microcontroller [ARM Cortex M4] [CDC/ACM serial port]
        5730  Audio Speaker
        5731  Microphone
        5740  Virtual COM Port
        e07a  Broadcom BCM20702A1 Bluetooth
        e0c8  MediaTek MT7921 Bluetooth
        e0cd  MediaTek Bluetooth Adapter
-       e0d8  Bluetooth Adapter
+       e0d8  Bluetooth 5.2 Adapter [MediaTek MT7922]
 048a  S-MOS Systems, Inc.
 048c  Alps Electric Ireland, Ltd
 048d  Integrated Technology Express, Inc.
        0320  Bluetooth Adapter
        0321  Bluetooth Device
        0a28  INDI AV-IN Device
+       1301  Network Controller
+       1302  i3 Gateway
+       1303  3 Micro Module
+       1304  i3 Module
+       1305  i3 Multi Sensing Module
 04c1  U.S. Robotics (3Com)
        0020  56K Voice Pro
        0022  56K Voice Pro
        072d  Revio KD410Z
 04ca  Lite-On Technology Corp.
        0020  USB Keyboard
+       003a  Multimedia Keyboard
        004b  Keyboard
        004f  SK-9020 keyboard
        008a  Acer Wired Mouse Model SM-9023
        1400  PS/2 keyboard + mouse controller
        1503  Keyboard
        1603  Keyboard
+       1605  Keyboard
        1702  Keyboard LKS02
        1818  Keyboard [Diatec Filco Majestouch 2]
        2011  Keyboard [Diatec Filco Majestouch 1]
        b681  ThinkPad T490 Webcam
        b71a  Integrated IR Camera
        b76b  SunplusIT Inc [HP HD Camera]
+       b7b4  Integrated Camera (1920x1080)
 04f3  Elan Microelectronics Corp.
        000a  Touchscreen
        0103  ActiveJet K-2024 Multimedia Keyboard
        0003  Smart Card Reader II
 04fe  PFU, Ltd
        0006  Happy Hacking Keyboard Lite2
+       0020  HHKB-Classic
+       0021  Happy Hacking Keyboard Professional HYBRID Type-S
 04ff  E-CMOS Corp.
 0500  Siam United Hi-Tech
        0001  DART Keyboard Mouse
        0081  F8T001v2 Bluetooth
        0083  Bluetooth Device
        0084  F8T003v2 Bluetooth
+       008a  6-in-1 Multiport Adapter
        0102  Flip KVM
        0103  F5U103 Serial Adapter [etek]
        0106  VideoBus II Adapter, Video
        05c4  DualShock 4 [CUH-ZCT1x]
        0643  DSC-H100 in PTP/MTP mode
        0689  Walkman NWZ-B173F
+       068c  UP-D711
        06bb  WALKMAN NWZ-F805
        06c3  RC-S380
        07c3  ILCE-6000 (aka Alpha-6000) in Mass Storage mode
        03ac  DTH-W1620 [MobileStudio Pro 16] touchscreen
        03b2  DTH167 [Cintiq Pro 16] tablet
        03b3  DTH167 [Cintiq Pro 16] touchscreen
+       03c0  DTH271 [Cintiq Pro 27] touchscreen
+       03c4  DTH172 [Cintiq Pro 17]
        03c5  CTL-4100WL [Intuos BT (S)]
        03c7  CTL-6100WL [Intuos BT (M)]
+       03cb  DTH134 [Wacom One 13] touchscreen
+       03ce  DTC121 [Wacom One 12] touchscreen
+       03d0  DTH227 [Cintiq Pro 22]
        03dc  PTH-460 [Intuos Pro (S)] tablet
        03dd  PTH-460 [Intuos Pro BT (S)] tablet
+       03ec  DTH134 [DTH134] touchscreen
+       03ed  DTC121 [DTC121] touchscreen
        0400  PenPartner 4x5
        4001  TPC4001
        4004  TPC4004
        0002  HID Monitor Controls
        0003  Device Bay Controller
        4000  FlexScan EV3237
-       4001  Monitor
-       4002  USB HID Monitor
+       4001  FlexScan EV2450
+       4002  FlexScan EV2455
        4014  FlexScan EV2750
        4026  FlexScan EV2451
        4027  FlexScan EV2456
+       402b  FlexScan EV2780
        4036  FlexScan EV2785
        4037  FlexScan EV3285
        4044  FlexScan EV2457
        4059  FlexScan EV2760
        405a  FlexScan EV2360
        405b  FlexScan EV2460
+       405e  FlexScan EV2495
        405f  FlexScan EV2795
        4065  FlexScan EV3895
+       406a  FlexScan EV2480
 056e  Elecom Co., Ltd
        0002  29UO Mouse
        0057  Micro Grast Pop M-PGDL
        1093  Rugged
        1094  Rugged THB
        1095  Rugged
+       1105  Mobile Drive (RLSD: 2022)
        a601  HardDrive
        a602  CD R/W
 05a0  Vetronix Corp.
 05e4  Red Wing Corp.
 05e5  Fuji Electric Co., Ltd
 05e6  Keithley Instruments
+       3390  3390 Arbitrary Waveform Generator
 05e8  ICC, Inc.
 05e9  Kawasaki LSI
        0008  KL5KUSB101B Ethernet [klsi]
 # typo?
        4004  Minolta Dimage Scan Elite II AF-2920 (2888)
 0639  Chrontel, Inc.
+       7213  CH7213
+       7231  CH7213
 063a  Techwin Corp.
 063b  Taugagreining HF
 063c  Yamaichi Electronics Co., Ltd (Sakura)
        00bd  Prometheus MIS Touch Fingerprint Reader
        00c7  TouchPad
        00cb  Fingerprint scanner
+       00fc  Prometheus Fingerprint Reader
        0ac3  Large Touch Screen
        2970  touchpad
 06cc  Terayon Communication Systems
        038c  CP900DW(ID) Port
        0393  CP9500D/DW Port
        0394  CP9000D/DW Port
+       0395  CP9000DW
        0398  P93D
+       039e  CP9500DW-S
        03a1  CP9550D/DW Port
        03a5  CP9550DW-S
        03a9  CP-9600DW
        03ae  CP-9800DW-S
        0f10  Hori/Namco FlightStick 2
        3b10  P95D
+       3b20  CP9820DW Series
        3b21  CP-9810D/DW
+       3b2f  LS9820A
        3b30  CP-D70DW / CP-D707DW
        3b31  CP-K60DW-S
        3b36  CP-D80DW
        c007  DPB-4000
        c009  DPB-6000
        c010  CPB-7000
+       c011  ASK-2500
 07cf  Casio Computer Co., Ltd
        1001  QV-8000SX/5700/3000EX Digicam; Exilim EX-M20
        1003  Exilim EX-S500
        0000  FastLane MIDI Interface
        0001  MIDI Interface
        0002  MOTU Audio for 64 bit
-       0004  MicroBook
+       0004  Microbook I/II/IIc
        0008  M Series
+       0009  M Series (firmware update mode)
+       000b  M Series
+       000d  M Series (firmware update mode)
 07ff  Unknown
        00ff  Portable Hard Drive
        ffff  Mad Catz Gamepad
 0826  Data Transit
 0827  BroadLogic, Inc.
 0828  Sato Corp.
+       a003  WS408 Label Printer
 0829  DirecTV Broadband, Inc. (Telocity)
 082d  Handspring
        0100  Visor
        04b2  NC interface
        04b3  keyboard front panel Cockpit
        04b4  SCR_CCID
+       04b5  Camera
+       04b6  Cockpit Touchkeypad
+       04b7  Cockpit Touchkeypad Bootloader
+       04b8  MediSET USB4-W
+       04b9  MediSET USB4-R
+       04ba  MediSET USB4-G
        2701  ShenZhen SANZHAI Technology Co.,Ltd Spy Pen VGA
 0909  Audio-Technica Corp.
        001b  ATR2100-USB
        037c  300k Pixel Camera
        1000  Flash Drive
        1132  5-in-1 Card Reader
+       2000  Disk
        337b  Silicon Motion Camera
        3710  Silicon Motion Camera
        3720  Silicon Motion Camera
        4cda  Fenix 6 Sapphire
        4cdb  Fenix 6
 0920  Echelon Co.
+       5550  U60 FT Network Interface
        7500  Network Interface
 0921  GoHubs, Inc.
        1001  GoCOM232 Serial
        010f  nanoKONTROL studio controller
        0117  nanoKONTROL2 MIDI Controller
        012f  SQ-1
+       0203  KRONOS
        0f03  K-Series K61P MIDI studio controller
 0945  Pasco Scientific
 0948  Kronauer music in digital
        7140  T124 [Tegra K1/Logan 32-bit]
        7210  SHIELD Controller
        7321  Switch [Tegra Erista] recovery mode
+       7323  T234 [Orin NX 16GB] recovery mode
+       7423  T234 [Orin NX 8GB] recovery mode
        7721  T210 [TX1 Tegra Erista] recovery mode
        7820  T20 [Tegra 2] recovery mode
        7c18  T186 [TX2 Tegra Parker] recovery mode
        cf09  SHIELD Tablet
 0956  BSquare Corp.
 0957  Agilent Technologies, Inc.
+       0007  82357A GPIB Interface Firmware loader
+       0107  82357A GPIB Interface
        0200  E-Video DC-350 Camera
        0202  E-Video DC-350 Camera
        0407  33220A Waveform Generator
-       0518  82357B GPIB Interface
+       0518  82357B GPIB Interface Firmware loader
+       0607  34410A Multimeter
+       0718  82357B GPIB Interface
        0a07  34411A Multimeter
        1507  33210A Waveform Generator
        1745  Test and Measurement Device (IVI)
+       1907  53230A Frequency Counter
        1f01  N5181A MXG Analog Signal Generator
        2918  U2702A oscilloscope
        fb18  LC Device
        6330  SANWA Supply Inc. Slim Keyboard
        713a  WK-713 Multimedia Keyboard
        7160  Hyper Slim Keyboard
+       7202  Enermax Aurora Micro Wireless Receiver
 099e  Trimble Navigation, Ltd
 09a3  PairGain Technologies
 09a4  Contech Research, Inc.
 09d8  ELATEC GmbH
        0320  TWN3 Multi125
        0406  TWN4 MIFARE NFC
+       0410  TWN4 HID
+       0420  TWN4 CDC
 09d9  KRF Tech, Ltd
 09da  A4Tech Co., Ltd.
        0006  Optical Mouse WOP-35 / Trust 450L Optical Mouse
        0018  Trust Human Interface Device
        001a  Wireless Mouse & RXM-15 Receiver
        002a  Wireless Optical Mouse NB-30
+       0103  Oscar X-710BK Gaming Mouse
        022b  Wireless Mouse (Battery Free)
        024f  RF Receiver and G6-20D Wireless Optical Mouse
        0260  KV-300H Isolation Keyboard
        09da  Bloody V8 Mouse
        1068  Bloody A90 Mouse
        112c  Bloody V5 Mouse
+       2268  Keyboard (FK11)
+       2690  PK-635G
        3a60  Bloody V8M Core 2 Mouse
        8090  X-718BK Oscar Optical Gaming Mouse
        9033  X-718BK Optical Mouse
        9066  F3 V-Track Gaming Mouse
-       9090  XL-730K / XL-750BK / XL-755BK Mice
+       9090  XL-730K / XL-747H / XL-750BK / XL-755BK Mice
        f613  Bloody V7M Mouse
+       f6cc  B314 Light Strike Gaming Keyboard
+       fa44  B930 Light Strike RGB Mechanical Gaming Keyboard
 09db  Measurement Computing Corp.
        0075  MiniLab 1008
        0076  PMD-1024
 09e6  Silutia, Inc.
 09e7  Real 3D, Inc.
 09e8  AKAI  Professional M.I. Corp.
+       0029  APC40 mkII
        0045  MPK Mini Mk II MIDI Controller
        0062  MPD16 MIDI Pad Controller Unit
        006d  EWI electronic wind instrument
        0071  MPK25 MIDI Keyboard
        0076  LPK25 MIDI Keyboard
+       007c  MPK Mini MIDI Controller
 09e9  Chen-Source, Inc.
 09eb  IM Networks, Inc.
        4331  iRhythm Tuner Remote
        1010  Bluetooth Device
        1011  Bluetooth Device
        1012  Bluetooth Device
+       1243  CSRA64210 [TaoTronics Headset BH-22 in charging mode]
+       4007  Mpow HC5 Headset in charging mode - HID / Mass Storage
+       4010  Mpow HC5 Headset in charging mode - USB Hub
        ffff  USB Bluetooth Device in DFU State
 0a13  Telebyte, Inc.
 0a14  Spacelabs Medical, Inc.
 0a35  Radikal Technologies
        002a  SAC - Software Assigned Controller
        008a  SAC Hub
+0a38  IRIS sa
 0a39  Gilat Satellite Networks, Ltd
 0a3a  PentaMedia Co., Ltd
        0163  KN-W510U 1.0 Wireless LAN Adapter
        217f  BCM2045B (BDC-2.1)
        2198  Bluetooth 3.0 Device
        219b  Bluetooth 2.1 Device
+       219c  BCM2070 Bluetooth
        21b1  HP Bluetooth Module
        21b4  BCM2070 Bluetooth 2.1 + EDR
        21b9  BCM2070 Bluetooth 2.1 + EDR
        5802  BCM5880 Secure Applications Processor with fingerprint touch sensor
        5803  BCM5880 Secure Applications Processor with secure keyboard
        5804  BCM5880 Secure Applications Processor with fingerprint swipe sensor
+       5832  BCM5880 Secure Applications Processor Smartcard reader
        6300  Pirelli Remote NDIS Device
        6410  BCM20703A1 Bluetooth 4.1 + LE
        bd11  BCM4320 802.11bg Wireless Adapter
 20a0  Clay Logic
        0006  flirc
        4107  GPF Crypto Stick V1.2
+       4108  Nitrokey Pro
+       4109  Nitrokey Storage
        4123  IKALOGIC SCANALOGIC 2
        414a  MDE SPI Interface
        415a  OpenPilot
        41e5  BlinkStick
        4211  Nitrokey Start
        4223  ATSAMD21 [castAR]
+       4230  Nitrokey HSM
+       4287  Nitrokey FIDO U2F
        428d  Electrosense wideband converter
+       42b1  Nitrokey FIDO2
+       42b2  Nitrokey 3A Mini/3A NFC/3C NFC
+       42b4  Nitrokey Pro Bootloader
+       42da  MuteMe
+       42dd  Nitrokey 3A NFC Bootloader/3C NFC Bootloader
+       42e8  Nitrokey 3A Mini Bootloader
+       42ec  RP2040 [PicoWifi]
 20b1  XMOS Ltd
        10ad  XUSB Loader
        f7d1  XTAG2 - JTAG Adapter
 2581  Plug-up
        1807  Generic HID Smartcard
        1808  WinUSB Smartcard
-       f1d0  FIDO U2F Security Key
+       f1d0  Nitrokey U2F
 258d  Sequans Communications
 259a  TriQuint Semiconductor
 25a7  Areson Technology Corp
index 0113d1b6bb259dc5b7446a78c7590df503011182..58a285c83359e2590e5d63880289348a70cb350d 100644 (file)
       <term><varname>$SYSTEMD_LOG_LEVEL</varname></term>
 
       <listitem><para id='log-level-body'>The maximum log level of emitted messages (messages with a higher
-      log level, i.e. less important ones, will be suppressed). Either one of (in order of decreasing
-      importance) <constant>emerg</constant>, <constant>alert</constant>, <constant>crit</constant>,
-      <constant>err</constant>, <constant>warning</constant>, <constant>notice</constant>,
-      <constant>info</constant>, <constant>debug</constant>, or an integer in the range 0…7. See
+      log level, i.e. less important ones, will be suppressed). Takes a comma-separated list of values. A
+      value may be either one of (in order of decreasing importance) <constant>emerg</constant>,
+      <constant>alert</constant>, <constant>crit</constant>, <constant>err</constant>,
+      <constant>warning</constant>, <constant>notice</constant>, <constant>info</constant>,
+      <constant>debug</constant>, or an integer in the range 0…7. See
       <citerefentry project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-      for more information.</para>
-      </listitem>
+      for more information. Each value may optionally be prefixed with one of <constant>console</constant>,
+      <constant>syslog</constant>, <constant>kmsg</constant> or <constant>journal</constant> followed by a
+      colon to set the maximum log level for that specific log target (e.g.
+      <constant>SYSTEMD_LOG_LEVEL=debug,console:info</constant> specifies to log at debug level except when
+      logging to the console which should be at info level). Note that the global maximum log level takes
+      priority over any per target maximum log levels.</para></listitem>
     </varlistentry>
 
     <varlistentry id='log-color'>
index 1d92745eb42ad9529f347193f0ebc45b74e0df78..955111fe940a2af40cc7d53ba85b8b8595a33f2c 100644 (file)
 
     <para>For the latter five mechanisms the source for the key material used for unlocking the volume is
     primarily configured in the third field of each <filename>/etc/crypttab</filename> line, but may also
-    configured in <filename>/etc/cryptsetup-keys.d/</filename> and
+    be configured in <filename>/etc/cryptsetup-keys.d/</filename> and
     <filename>/run/cryptsetup-keys.d/</filename> (see above) or in the LUKS2 JSON token header (in case of
     the latter three). Use the
     <citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     is acquired by connecting to the socket and reading the key from the connection. The connection is made
     from an <constant>AF_UNIX</constant> socket name in the abstract namespace, see <citerefentry
     project='man-pages'><refentrytitle>unix</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
-    details. The source socket name is chosen according the following format:</para>
+    details. The source socket name is chosen according to the following format:</para>
 
     <programlisting><constant>NUL</constant> <replaceable>RANDOM</replaceable> /cryptsetup/ <replaceable>VOLUME</replaceable></programlisting>
 
index dc51041138bf03cbffe401f7773658b4a45e1a83..42630d2782573d8c5e8d7628164b8b2a375d39f5 100644 (file)
         <listitem><para>If the service opens sockets or other files on it own, and those file descriptors
         shall survive a restart, the daemon should store them in the service manager via
         <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> with
-        <varname>FDSTORE=1</varname>..</para></listitem>
+        <varname>FDSTORE=1</varname>.</para></listitem>
 
         <listitem><para>Instead of using the <function>syslog()</function> call to log directly to the system
         syslog service, a new-style daemon may choose to simply log to standard error via
index 25c49fc5dc9afcc88732c4625c89c25cca71d857..3e2e33f685b26a2a7e6b99753eb07f73ad9b07f4 100644 (file)
@@ -36,7 +36,7 @@
   <refsect1>
     <title>Description</title>
 
-    <para><command>importctl</command> may be used to download, import export disk images via
+    <para><command>importctl</command> may be used to download, import, and export disk images via
     <citerefentry><refentrytitle>systemd-importd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
 
     <para><command>importctl</command> operates both on block-level disk images (such as DDIs) as well as
index ea517f4ac4e08ecf3ae14f834078396af9dd8dce..7d6820064ec792922fac3999ffc41510ba56e022 100644 (file)
   <refsect1>
     <title>Commands</title>
 
-    <para>The following commands are understood. If none is specified the default is to display journal records.</para>
+    <para>The following commands are understood. If none is specified the default is to display journal records:</para>
 
     <variablelist>
       <varlistentry>
index 8ac3d96086c291af6ebec9313caf2f505e059276..6fe3bb3ce0821abf45ace659dcbe9e3008771665 100644 (file)
@@ -112,8 +112,6 @@ node /org/freedesktop/home1 {
                           out h send_fd);
       @org.freedesktop.systemd1.Privileged("true")
       ReleaseHome(in  s user_name);
-      InhibitSuspendHome(in  s user_name,
-                         out h send_fd);
       @org.freedesktop.systemd1.Privileged("true")
       LockAllHomes();
       @org.freedesktop.systemd1.Privileged("true")
@@ -187,8 +185,6 @@ node /org/freedesktop/home1 {
 
     <variablelist class="dbus-method" generated="True" extra-ref="ReleaseHome()"/>
 
-    <variablelist class="dbus-method" generated="True" extra-ref="InhibitSuspendHome()"/>
-
     <variablelist class="dbus-method" generated="True" extra-ref="LockAllHomes()"/>
 
     <variablelist class="dbus-method" generated="True" extra-ref="DeactivateAllHomes()"/>
@@ -208,7 +204,9 @@ node /org/freedesktop/home1 {
       the numeric UID and GID, the real name, home directory and shell. In addition it returns a state
       identifier describing the state the user's home directory is in, as well as a bus path referring to the
       bus object encapsulating the user record and home directory. This object implements the
-      <classname>org.freedesktop.home1.Home</classname> interface documented below.</para>
+      <classname>org.freedesktop.home1.Home</classname> interface documented below. This method, and most others
+      in this interface that take user names, will try to use the caller's home area if the specified user name is
+      an empty string.</para>
 
       <para><function>GetHomeByUID()</function> is similar to <function>GetHomeByName()</function> but
       acquires the information based on the numeric UID of the user.</para>
@@ -387,10 +385,9 @@ node /org/freedesktop/home1 {
       re-authenticate when the system comes back from suspending. It should be set by all clients that
       implement a secure lock screen running outside of the user's context, that is brought up when the
       system comes back from suspend and can be used to re-acquire the credentials to unlock the user's home
-      directory. A home directory is locked automatically at system suspend only if all clients with open
-      references to the home directory specify that they support this functionality, and no client has
-      temporarily inhibited it (see <function>InhibitSuspendHome()</function> below); otherwise the directory
-      remains unlocked. This method is equivalent to <function>Acquire()</function> on the
+      directory. If a home directory has at least one client with an open reference to the home directory
+      that does not support this it is not suspended automatically at system suspend, otherwise it is. This
+      method is equivalent to <function>Acquire()</function> on the
       <classname>org.freedesktop.home1.Home</classname> interface.</para>
 
       <para><function>RefHome()</function> is similar to <function>AcquireHome()</function> but takes no user
@@ -412,25 +409,9 @@ node /org/freedesktop/home1 {
       triggered deactivation is completed. This method is equivalent to <function>Release()</function> on the
       <classname>org.freedesktop.home1.Home</classname> interface.</para>
 
-      <para><function>InhibitSuspendHome()</function> temporarily inhibits automatic locking during system
-      suspend for a home directory. It returns a file descriptor that inhibits this functionality for as long
-      as it is open. As mentioned above, locking a home directory requires a secure lock screen running
-      outside of the user context, and is likely to freeze any process that attempts to access the directory.
-      Thus, locking a home directory is a trade-off: it increases security, but prevents the client from
-      displaying any user content on its secure lock screen, including notifications, media controls, contact
-      information for incoming phone calls, and much more. A client may use this method to implement more
-      complicated automatic locking behavior for home directories, in order to solve some of these UX issues.
-      For instance, the client may choose to only lock the home directory and switch to the secure lock screen
-      if the device has been suspended for over 24 hours. Note that this inhibitor does not prevent clients from
-      calling <function>LockHome()</function>, and in fact clients will need to call <function>LockHome()</function>
-      manually as part of their custom behavior to lock the home directory. Clients should take care to ensure that
-      the file descriptor is closed in the event that their custom behavior fails or is disabled. This method is
-      equivalent to <function>InhibitSuspend()</function> on the <classname>org.freedesktop.home1.Home</classname>
-      interface.</para>
-
       <para><function>LockAllHomes()</function> locks all active home directories that only have references
-      that opted into automatic locking during system suspend and have no clients inhibiting this behavior.
-      This is usually invoked automatically shortly before system suspend.</para>
+      that opted into automatic suspending during system suspend. This is usually invoked automatically
+      shortly before system suspend.</para>
 
       <para><function>DeactivateAllHomes()</function> deactivates all home areas that are currently
       active. This is usually invoked automatically shortly before system shutdown.</para>
@@ -492,7 +473,6 @@ node /org/freedesktop/home1/home {
                       out h send_fd);
       @org.freedesktop.systemd1.Privileged("true")
       Release();
-      InhibitSuspend(out h send_fd);
     properties:
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s UserName = '...';
@@ -556,8 +536,6 @@ node /org/freedesktop/home1/home {
 
     <variablelist class="dbus-method" generated="True" extra-ref="Release()"/>
 
-    <variablelist class="dbus-method" generated="True" extra-ref="InhibitSuspend()"/>
-
     <variablelist class="dbus-property" generated="True" extra-ref="UserName"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="UID"/>
@@ -579,14 +557,15 @@ node /org/freedesktop/home1/home {
       <function>Update()</function>, <function>UpdateEx()</function>, <function>Resize()</function>,
       <function>ChangePassword()</function>, <function>Lock()</function>, <function>Unlock()</function>,
       <function>Acquire()</function>, <function>Ref()</function>, <function>RefUnrestricted()</function>,
-      <function>Release()</function>, <function>InhibitSuspend()</function> operate like their matching counterparts
-      on the <classname>org.freedesktop.home1.Manager</classname> interface (see above). The main difference is that
-      they are methods of the home directory objects, and hence carry no additional user name
-      parameter. Which of the two flavors of methods to call depends on the handles to the user known on the
-      client side: if only the user name is known, it's preferable to use the methods on the manager object
-      since they operate with user names only. If however the home object path was already acquired some way
-      it is preferable to operate on the <classname>org.freedesktop.home1.Home</classname> objects
-      instead.</para>
+      <function>Release()</function>,
+      operate like their matching counterparts on the <classname>org.freedesktop.home1.Manager</classname>
+      interface (see above). The main difference is that they are methods of the home directory objects, and
+      hence carry no additional user name parameter. Which of the two flavors of methods to call depends on
+      the handles to the user known on the client side: if only the user name is known, it's preferable to use
+      the methods on the manager object since they operate with user names only. Clients can also easily operate
+      on their own home area by using the methods on the manager object with an empty string as the user name.
+      If the client has the home's object path already acquired in some way, however, it is preferable to operate
+      on the <classname>org.freedesktop.home1.Home</classname> objects instead.</para>
     </refsect2>
 
     <refsect2>
@@ -611,12 +590,12 @@ node /org/freedesktop/home1/home {
     <title>History</title>
     <refsect2>
       <title>The Manager Object</title>
-      <para><function>InhibitSuspendHome()</function>, <function>ActivateHomeIfReferenced()</function>, <function>RefHomeUnrestricted()</function>,
+      <para><function>ActivateHomeIfReferenced()</function>, <function>RefHomeUnrestricted()</function>,
       <function>CreateHomeEx()</function>, and <function>UpdateHomeEx()</function> were added in version 256.</para>
     </refsect2>
     <refsect2>
       <title>Home Objects</title>
-      <para><function>InhibitSuspend()</function>, <function>ActivateIfReferenced()</function>, <function>RefUnrestricted()</function>, and
+      <para><function>ActivateIfReferenced()</function>, <function>RefUnrestricted()</function>, and
       <function>UpdateEx()</function> were added in version 256.</para>
     </refsect2>
   </refsect1>
index 5223131368fed17cbfc0e6a075165748ad62a74f..9651112f9780950b2126fdee4736b34d5df35398 100644 (file)
         multiple times, in which case the order in which images are laid down follows the rules specified in
         <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
         for the <varname>ExtensionImages=</varname> directive and for the
-        <citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry> and.
+        <citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry> and
         <citerefentry><refentrytitle>systemd-confext</refentrytitle><manvolnum>8</manvolnum></citerefentry> tools.
         The images must contain an <filename>extension-release</filename> file with metadata that matches
         what is defined in the <filename>os-release</filename> of <replaceable>IMAGE</replaceable>. See:
index 50a2de7c33d6500901e539ebe17f1dcaa507e179..fb32e2dc46924bcd95f04d60f716cde408856941 100644 (file)
 
         <para>The file specified here must have a size that is a multiple of the basic block size 512 and not
         be empty. If this option is used, the size allocation algorithm is slightly altered: the partition is
-        created as least as big as required to fit the data in, i.e. the data size is an additional minimum
+        created at least as big as required to fit the data in, i.e. the data size is an additional minimum
         size value taken into consideration for the allocation algorithm, similar to and in addition to the
         <varname>SizeMin=</varname> value configured above.</para>
 
         <literal>squashfs</literal> or the special value <literal>swap</literal>. If specified and the partition
         is newly created it is formatted with the specified file system (or as swap device). The file system
         UUID and label are automatically derived from the partition UUID and label. If this option is used,
-        the size allocation algorithm is slightly altered: the partition is created as least as big as
+        the size allocation algorithm is slightly altered: the partition is created at least as big as
         required for the minimal file system of the specified type (or 4KiB if the minimal size is not
         known).</para>
 
index 1f07e606c9689f75f6ac1bf16f4ac9771132f099..38a0749fc75276df59a798671ec9fcea6cabc18b 100644 (file)
@@ -75,6 +75,7 @@ manpages = [
  ['repart.d', '5', [], 'ENABLE_REPART'],
  ['resolvectl', '1', ['resolvconf'], 'ENABLE_RESOLVE'],
  ['resolved.conf', '5', ['resolved.conf.d'], 'ENABLE_RESOLVE'],
+ ['run0', '1', [], ''],
  ['runlevel', '8', [], 'HAVE_SYSV_COMPAT'],
  ['sd-bus-errors',
   '3',
@@ -795,7 +796,7 @@ manpages = [
    'sd_journal_seek_realtime_usec',
    'sd_journal_seek_tail'],
   ''],
- ['sd_journal_stream_fd', '3', [], ''],
+ ['sd_journal_stream_fd', '3', ['sd_journal_stream_fd_with_namespace'], ''],
  ['sd_listen_fds',
   '3',
   ['SD_LISTEN_FDS_START', 'sd_listen_fds_with_names'],
@@ -1265,7 +1266,6 @@ manpages = [
   ''],
  ['udev_new', '3', ['udev_ref', 'udev_unref'], ''],
  ['udevadm', '8', [], ''],
- ['uid0', '1', [], ''],
  ['ukify', '1', [], 'ENABLE_UKIFY'],
  ['user@.service',
   '5',
similarity index 93%
rename from man/uid0.xml
rename to man/run0.xml
index f0bfa40b9d95c347c01d5ea5138f6e66f634dee5..09e5620cce5a39f8b79a968b32e67eeae130fb2f 100644 (file)
@@ -3,27 +3,27 @@
   "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
 <!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
 
-<refentry id="uid0"
+<refentry id="run0"
           xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
-    <title>uid0</title>
+    <title>run0</title>
     <productname>systemd</productname>
   </refentryinfo>
 
   <refmeta>
-    <refentrytitle>uid0</refentrytitle>
+    <refentrytitle>run0</refentrytitle>
     <manvolnum>1</manvolnum>
   </refmeta>
 
   <refnamediv>
-    <refname>uid0</refname>
+    <refname>run0</refname>
     <refpurpose>Elevate privileges</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
     <cmdsynopsis>
-      <command>uid0</command>
+      <command>run0</command>
       <arg choice="opt" rep="repeat">OPTIONS</arg>
       <arg choice="opt" rep="repeat">COMMAND</arg>
     </cmdsynopsis>
@@ -32,7 +32,7 @@
   <refsect1>
     <title>Description</title>
 
-    <para><command>uid0</command> may be used to temporarily and interactively acquire elevated or different
+    <para><command>run0</command> may be used to temporarily and interactively acquire elevated or different
     privileges. It serves a similar purpose as <citerefentry
     project='man-pages'><refentrytitle>sudo</refentrytitle><manvolnum>8</manvolnum></citerefentry>, but
     operates differently in a couple of key areas:</para>
     setting the <varname>NoNewPrivileges=</varname> variable in
     <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>).</para>
 
-    <para>Any session invoked via <command>uid0</command> will run through the
-    <literal>systemd-uid0</literal> PAM stack.</para>
+    <para>Any session invoked via <command>run0</command> will run through the
+    <literal>systemd-run0</literal> PAM stack.</para>
 
-    <para>Note that <command>uid0</command> is implemented as an alternative multi-call invocation of
+    <para>Note that <command>run0</command> is implemented as an alternative multi-call invocation of
     <citerefentry><refentrytitle>systemd-run</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
   </refsect1>
 
         <term><option>--slice-inherit</option></term>
 
         <listitem><para>Make the new <filename>.service</filename> unit part of the slice the
-        <command>uid0</command> itself has been invoked in. This option may be combined with
+        <command>run0</command> itself has been invoked in. This option may be combined with
         <option>--slice=</option>, in which case the slice specified via <option>--slice=</option> is placed
-        within the slice the <command>uid0</command> command is invoked in.</para>
+        within the slice the <command>run0</command> command is invoked in.</para>
 
-        <para>Example: consider <command>uid0</command> being invoked in the slice
+        <para>Example: consider <command>run0</command> being invoked in the slice
         <filename>foo.slice</filename>, and the <option>--slice=</option> argument is
         <filename>bar</filename>. The unit will then be placed under
         <filename>foo-bar.slice</filename>.</para>
   <refsect1>
     <title>Exit status</title>
 
-    <para>On success, 0 is returned. If <command>uid0</command> failed to start the session or the specified command fails, a
+    <para>On success, 0 is returned. If <command>run0</command> failed to start the session or the specified command fails, a
     non-zero return value will be returned.</para>
   </refsect1>
 
index 13939ff19e4e5dadfda32e38c61f047d196d77ec..ff0d2eedd939c6c014f4474098bb2761bcc6c286 100644 (file)
@@ -17,6 +17,7 @@
 
   <refnamediv>
     <refname>sd_journal_stream_fd</refname>
+    <refname>sd_journal_stream_fd_with_namespace</refname>
     <refpurpose>Create log stream file descriptor to the journal</refpurpose>
   </refnamediv>
 
         <paramdef>int <parameter>level_prefix</parameter></paramdef>
       </funcprototype>
 
+      <funcprototype>
+        <funcdef>int <function>sd_journal_stream_fd_with_namespace</function></funcdef>
+        <paramdef>const char *<parameter>name_space</parameter></paramdef>
+        <paramdef>const char *<parameter>identifier</parameter></paramdef>
+        <paramdef>int <parameter>priority</parameter></paramdef>
+        <paramdef>int <parameter>level_prefix</parameter></paramdef>
+      </funcprototype>
+
     </funcsynopsis>
   </refsynopsisdiv>
 
   <refsect1>
     <title>Description</title>
 
-    <para><function>sd_journal_stream_fd()</function> may be used to
-    create a log stream file descriptor. Log messages written to this
-    file descriptor as simple newline-separated text strings are
-    written to the journal. This file descriptor can be used
-    internally by applications or be made standard output or standard
-    error of other processes executed.</para>
+    <para><function>sd_journal_stream_fd()</function> may be used to create a log stream file descriptor.
+    Log messages written to this file descriptor as simple newline-separated text strings are written
+    to the journal. This file descriptor can be used internally by applications or be made standard output
+    or standard error of other processes executed.</para>
 
-    <para><function>sd_journal_stream_fd()</function> takes a short
-    program identifier string as first argument, which will be written
-    to the journal as SYSLOG_IDENTIFIER= field for each log entry
+    <para><function>sd_journal_stream_fd()</function> takes a short program identifier string as
+    first argument, which will be written to the journal as SYSLOG_IDENTIFIER= field for each log entry
     (see
     <citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>
-    for more information). The second argument shall be the default
-    priority level for all messages. The priority level is one of
+    for more information). The second argument shall be the default priority level for all messages.
+    The priority level is one of
     <constant>LOG_EMERG</constant>, <constant>LOG_ALERT</constant>,
     <constant>LOG_CRIT</constant>, <constant>LOG_ERR</constant>,
     <constant>LOG_WARNING</constant>, <constant>LOG_NOTICE</constant>,
     <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>
     for more information.</para>
 
-    <para>It is recommended that applications log UTF-8 messages only
-    with this API, but this is not enforced.</para>
+    <para><function>sd_journal_stream_fd_with_namespace()</function> is similar to
+    <function>sd_journal_stream_fd()</function>, but takes an additional <parameter>name_space</parameter> parameter
+    that specifies which journal namespace to operate on. If specified as <constant>NULL</constant> the call
+    is identical to <function>sd_journal_stream_fd()</function>. For details about journal namespaces, see
+    <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+
+    <para>It is recommended that applications log UTF-8 messages only with this API, but this is not enforced.</para>
 
-    <para>Each invocation of <function>sd_journal_stream_fd()</function> allocates a new log stream file descriptor,
-    that is not shared with prior or later invocations. The file descriptor is write-only (its reading direction is
-    shut down), and <constant>O_NONBLOCK</constant> is turned off initially.</para>
+    <para>Each invocation of these functions allocates a new log stream file descriptor,
+    that is not shared with prior or later invocations. The file descriptor is write-only (its reading direction
+    is shut down), and <constant>O_NONBLOCK</constant> is turned off initially.</para>
   </refsect1>
 
   <refsect1>
     <title>Return Value</title>
 
-    <para>The call returns a valid write-only file descriptor on
-    success or a negative errno-style error code.</para>
+    <para>The call returns a valid write-only file descriptor on success or a negative errno-style error code.</para>
   </refsect1>
 
   <refsect1>
     <title>Signal safety</title>
 
-    <para><function>sd_journal_stream_fd()</function> is "async signal safe" in the meaning of <citerefentry
+    <para><function>sd_journal_stream_fd()</function> and <function>sd_journal_stream_fd_with_namespace()</function>
+    are "async signal safe" in the meaning of <citerefentry
     project='man-pages'><refentrytitle>signal-safety</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
     </para>
   </refsect1>
   <refsect1>
     <title>History</title>
     <para><function>sd_journal_stream_fd()</function> was added in version 187.</para>
+    <para><function>sd_journal_stream_fd_with_namespace()</function> was added in version 256.</para>
   </refsect1>
 
   <refsect1>
index a56d03946868311bfccd0d332fbc25c37008223b..1e611fe6d86e0cf37872720070e54209c6c899b6 100644 (file)
     </variablelist>
 
     <para>The notification messages sent by services are interpreted by the service manager. Unknown
-    assignments may be logged, but are otherwise ignored. Thus, it is not useful to send assignments which
-    are not in this list. The service manager also sends some messages to <emphasis>its</emphasis>
-    notification socket, which are then consumed by the machine or container manager.</para>
+    assignments are ignored. Thus, it is is safe (but often without effect) to send assignments which are not
+    in this list. The protocol is extensible, but care should be taken to ensure private extensions are
+    recognizable as such. Specifically, it is recommend to prefix them with <literal>X_</literal> followed by
+    some namespace identifier. The service manager also sends some messages to <emphasis>its</emphasis>
+    notification socket, which may then consumed by a supervising machine or container manager further up the
+    stack. The service manager sends a number of extension fields, for example
+    <varname>X_SYSTEMD_UNIT_ACTIVE=</varname>, for details see
+    <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
   </refsect1>
 
   <refsect1>
     <constant>AF_VSOCK</constant> address, which is useful for hypervisors/VMMs or other processes on the
     host to receive a notification when a virtual machine has finished booting. Note that in case the
     hypervisor does not support <constant>SOCK_DGRAM</constant> over <constant>AF_VSOCK</constant>,
-    <constant>SOCK_SEQPACKET</constant> will be used instead. The address should be in the form:
-    <literal>vsock:CID:PORT</literal>. Note that unlike other uses of vsock, the CID is mandatory and cannot
-    be <literal>VMADDR_CID_ANY</literal>.  Note that PID1 will send the VSOCK packets from a privileged port
-    (i.e.: lower than 1024), as an attempt to address concerns that unprivileged processes in the guest might
-    try to send malicious notifications to the host, driving it to make destructive decisions based on
-    them.</para>
+    <constant>SOCK_SEQPACKET</constant> will be used instead. <literal>vsock-stream</literal>,
+    <literal>vsock-dgram</literal> and <literal>vsock-seqpacket</literal> can be used instead of
+    <literal>vsock</literal> to force usage of the corresponding socket type. The address should be in the
+    form: <literal>vsock:CID:PORT</literal>. Note that unlike other uses of vsock, the CID is mandatory and
+    cannot be <literal>VMADDR_CID_ANY</literal>.  Note that PID1 will send the VSOCK packets from a
+    privileged port (i.e.: lower than 1024), as an attempt to address concerns that unprivileged processes in
+    the guest might try to send malicious notifications to the host, driving it to make destructive decisions
+    based on them.</para>
   </refsect1>
 
   <refsect1>
index 043ee712540e3da7017797ecff12a9e29d3d832a..7ace7703b9aab14480fd151ebe549ad3a8f6efb1 100644 (file)
@@ -37,7 +37,7 @@
     boot counting is used.</para>
 
     <para>Internally, the service operates based on the <varname>LoaderBootCountPath</varname> EFI variable (of the
-    vendor UUID <constant>4a67b082-0a4c-41cf-b6c7-440b29bb8c4</constant>), which is passed from the boot loader to the
+    vendor UUID <constant>4a67b082-0a4c-41cf-b6c7-440b29bb8c4f</constant>), which is passed from the boot loader to the
     OS. It contains a file system path (relative to the EFI system partition) of the <ulink
     url="https://uapi-group.org/specifications/specs/boot_loader_specification">Boot Loader Specification</ulink> compliant boot loader entry
     file or unified kernel image file that was used to boot up the
index a4d1c003e0af192e22b8fe2440a239a9699c9b7f..cc4504926c85982e9fb0f26d769c78b51c4320d4 100644 (file)
     similar, to extend the native firmware support.</para>
 
     <para>Enrollment of Secure Boot variables can be performed manually or automatically if files are available
-    under <filename>/loader/keys/<replaceable>NAME</replaceable>/{db,KEK,PK}.auth</filename>, <replaceable>NAME</replaceable>
+    under <filename>/loader/keys/<replaceable>NAME</replaceable>/{db,dbx,KEK,PK}.auth</filename>, <replaceable>NAME</replaceable>
     being the display name for the set of variables in the menu. If one of the sets is named <filename>auto</filename>
     then it might be enrolled automatically depending on whether <literal>secure-boot-enroll</literal> is set
     to force or not.</para>
index 12667844853d6d9ce1e99b1756c476d05b5c81b1..e58d64c52ba699152ab23076937f8987bb5c439a 100644 (file)
@@ -19,7 +19,7 @@
   <refnamediv>
     <refname>systemd-bsod.service</refname>
     <refname>systemd-bsod</refname>
-    <refpurpose>Displays boot-time emergency log message in full screen.</refpurpose>
+    <refpurpose>Displays boot-time emergency log message in full screen</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
index 040da7c5c237c3629ab6865b2e9311ca89f0d68b..280492dea592bd7d349c66e6c22224b81a51311d 100644 (file)
         boolean argument.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--namespace=</option></term>
+
+        <listitem><para>Specifies the journal namespace to which the standard IO should be connected.
+        For details about journal namespaces, see
+        <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+        </para>
+
+        <xi:include href="version-info.xml" xpointer="v256"/></listitem>
+      </varlistentry>
+
     </variablelist>
 
   </refsect1>
   <refsect1>
     <title>Exit status</title>
 
-    <para>On success, 0 is returned, a non-zero failure code
-    otherwise.</para>
+    <para>On success, 0 is returned, a non-zero failure code otherwise.</para>
   </refsect1>
 
   <refsect1>
index 72dc56390ff17372a5ebbd0f5cb358e005a19c4b..4c139c5b45b60f316ba9a0c40bb9dd9626ba4fb1 100644 (file)
@@ -52,7 +52,7 @@
     <para><filename>systemd-cryptsetup</filename> is used to set up (with <command>attach</command>) and tear
     down (with <command>detach</command>) access to an encrypted block device. It is primarily used via
     <filename>systemd-cryptsetup@.service</filename> during early boot, but may also be be called manually.
-    The positional arguments <parameter>VOLUME</parameter>, <parameter>SOURCEDEVICE</parameter>,
+    The positional arguments <parameter>VOLUME</parameter>, <parameter>SOURCE-DEVICE</parameter>,
     <parameter>KEY-FILE</parameter>, and <parameter>CRYPTTAB-OPTIONS</parameter> have the same meaning as the
     fields in <citerefentry><refentrytitle>crypttab</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
     </para>
index 8f7e6d103d22dbba0b7c84d35189224f88f8b745..4b9c252784f8c13f4f0bdc873965e23d47561293 100644 (file)
@@ -1754,7 +1754,7 @@ After=sys-subsystem-net-devices-ens1.device</programlisting>
           <para>In order to embed binary data into the credential data for <option>--set-credential=</option>,
           use C-style escaping (i.e. <literal>\n</literal> to embed a newline, or <literal>\x00</literal> to
           embed a <constant>NUL</constant> byte). Note that the invoking shell might already apply unescaping
-          once, hence this might require double escaping!.</para>
+          once, hence this might require double escaping!</para>
 
           <para>The
           <citerefentry><refentrytitle>systemd-sysusers.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
index 58907f728c54f985c2a8e64dd9bc5e0941ed8788..2c674a34b4c0a94c4d8fe54853e33c5d794a510c 100644 (file)
 
         <listitem><para>Generates/removes a <filename>.pcrlock</filename> file based on raw binary data. The
         data is either read from the specified file or from STDIN (if none is specified). This requires that
-        <option>--pcrs=</option> is specified. The generated pcrlock file is written to the file specified
+        <option>--pcrs=</option> is specified. The generated .pcrlock file is written to the file specified
         via <option>--pcrlock=</option> or to STDOUT (if none is specified).</para>
 
         <xi:include href="version-info.xml" xpointer="v255"/>
       <varlistentry>
         <term><option>--nv-index=</option></term>
 
-        <listitem><para>Specifies to NV index to store the policy in. Honoured by
+        <listitem><para>Specifies the NV index to store the policy in. Honoured by
         <command>make-policy</command>. If not specified the command will automatically pick a free NV
         index.</para>
 
index 786bb6bf1323b8ed325107b55fd9ababfbfc5439..ec7ffdeb0d362d365bf9e696119deddb95e7b251 100644 (file)
@@ -60,7 +60,7 @@
     <literal>kexec</literal>, depending on the chosen action. All executables in this directory are executed
     in parallel, and execution of the action is not continued before all executables finished. Note that
     these executables are run <emphasis>after</emphasis> all services have been shut down, and after most
-    mounts have been detached (the root file system as well as <filename>/run/</filename> and various API
+    mounts have been unmounted (the root file system as well as <filename>/run/</filename> and various API
     file systems are still around though). This means any programs dropped into this directory must be
     prepared to run in such a limited execution environment and not rely on external services or hierarchies
     such as <filename>/var/</filename> to be around (or writable).</para>
index 7e2730a33a2baf0fde1f76bea802bc6ef19665e9..e719bd9687f66df088b3e24ef1b86f2493a6972b 100644 (file)
       <title>Generate a configuration extension image</title>
 
       <para>The following creates a configuration extension DDI (confext) for an
-      <filename>/etc/motd</filename> update.</para>
+      <filename>/etc/motd</filename> update:</para>
 
       <programlisting>mkdir tree tree/etc tree/etc/extension-release.d
 echo "Hello World" > tree/etc/motd
index e891920c630e57b90d13741fe9405c811d832149..c6fd4ac20c137fd5dad6471e7d636b82f1ca7649 100644 (file)
@@ -706,7 +706,7 @@ $ systemd-run --user --wait -p SuccessExitStatus=SIGUSR1 --expand-environment=no
       <member><citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>
       <member><citerefentry><refentrytitle>systemd-mount</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
       <member><citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
-      <member><citerefentry><refentrytitle>uid0</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
+      <member><citerefentry><refentrytitle>run0</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
     </simplelist></para>
   </refsect1>
 
index 138c919ee73a9181a15141e8c602b339bc420e95..26717e4259270f53d841e987006598602462b53b 100644 (file)
       via <varname>SurviveFinalKillSignal=yes</varname>, and also be configured to avoid being stopped on
       isolate via <varname>IgnoreOnIsolate=yes</varname>. They also have to be configured to be stopped on
       normal shutdown, reboot and maintenance mode. Finally, they have to be ordered after
-      <constant>basic.target</constant> to ensure correct ordeering on boot. Note that in case any new or
+      <constant>basic.target</constant> to ensure correct ordering on boot. Note that in case any new or
       custom units are used to isolate to, or that implement an equivalent shutdown functionality, they will
       also have to be configured manually for correct ordering and conflicting. For example:</para>
 
       <programlisting>[Unit]
-Description=My surviving service
+Description=My Surviving Service
 SurviveFinalKillSignal=yes
 IgnoreOnIsolate=yes
 DefaultDependencies=no
 After=basic.target
-Conflicts=reboot.target
-Before=reboot.target
-Conflicts=kexec.target
-Before=kexec.target
-Conflicts=poweroff.target
-Before=poweroff.target
-Conflicts=halt.target
-Before=halt.target
-Conflicts=rescue.target
-Before=rescue.target
-Conflicts=emergency.target
-Before=emergency.target
+Conflicts=reboot.target kexec.target poweroff.target halt.target rescue.target emergency.target
+Before=reboot.target kexec.target poweroff.target halt.target rescue.target emergency.target
 
 [Service]
 Type=oneshot
-ExecStart=sleep infinity
-      </programlisting>
+ExecStart=sleep infinity</programlisting>
       </listitem>
 
       <listitem><para>File system mounts may remain mounted during the transition, and complex storage
index 84e91dd47a06a41eefdf98bdcc9714353e4941b6..6fdbc3dc056c6b4384085a31d486871388581f70 100644 (file)
@@ -69,7 +69,7 @@
         exposed NVMe-TCP mass storage devices. The NQN should follow the syntax described in <ulink
         url="https://nvmexpress.org/wp-content/uploads/NVM-Express-Base-Specification-2.0c-2022.10.04-Ratified.pdf">NVM
         Express Base Specification 2.0c</ulink>, section 4.5 "NVMe Qualified Names". Note that the NQN
-        specified here will be suffixed with a dot and the the block device name before it is exposed on the
+        specified here will be suffixed with a dot and the block device name before it is exposed on the
         NVMe target. If not specified defaults to
         <literal>nqn.2023-10.io.systemd:storagetm.<replaceable>ID</replaceable></literal>, where ID is
         replaced by a 128bit ID derived from
index 8e5a6a6aa1bf2c3af534147aa952dfeb22912edb..df1f10aeefb487a63ee6e7da3834f15aaf62230e 100644 (file)
     but the used architecture identifiers are the same as for <varname>ConditionArchitecture=</varname>
     described in <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
     <varname>EXTENSION_RELOAD_MANAGER=</varname> can be set to 1 if the extension requires a service manager reload after application
-    of the extension. Note that the for the reasons mentioned earlier:
+    of the extension. Note that for the reasons mentioned earlier:
     <ulink url="https://systemd.io/PORTABLE_SERVICES">Portable Services</ulink> remain
     the recommended way to ship system services.
 
index 245d3444b1a8b7c096e4d6b69ffa9616fcc57c62..3fa3490995470fe7a4bd1f6b71856987d183105c 100644 (file)
@@ -37,7 +37,7 @@
 
     <para>The services will store the public key of the SRK key pair in a PEM file in
     <filename>/run/systemd/tpm2-srk-public-key.pem</filename> and
-    <filename>/var/lib/systemd/tpm2-srk-public-key.pem</filename>. It will also store it in TPM2B_PUBLIC
+    <filename>/var/lib/systemd/tpm2-srk-public-key.pem</filename>. They will also store it in TPM2B_PUBLIC
     format in <filename>/run/systemd/tpm2-srk-public-key.tpm2_public</filename> and
     <filename>/var/lib/systemd/tpm2-srk-public-key.tpm2b_public</filename>.</para>
 
index ef4d3ca2b629736570093875d95a57ae27079cb8..90ddc9b6740ba3afde539932cd1eb0bd5cf660cd 100644 (file)
@@ -18,7 +18,7 @@
 
   <refnamediv>
     <refname>systemd-vmspawn</refname>
-    <refpurpose>Spawn an OS in a virtual machine.</refpurpose>
+    <refpurpose>Spawn an OS in a virtual machine</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
           <xi:include href="version-info.xml" xpointer="v256"/>
           </listitem>
         </varlistentry>
+
+        <varlistentry>
+          <term><option>--pass-ssh-key=</option><replaceable>BOOL</replaceable></term>
+
+          <listitem><para>By default an SSH key is generated to allow <command>systemd-vmspawn</command> to open
+          a D-Bus connection to the VM's systemd bus. Setting this to "no" will disable SSH key generation.</para>
+
+          <para>The generated keys are ephemeral. That is they are valid only for the current invocation of <command>systemd-vmspawn</command>,
+          and are typically not persisted.</para>
+
+          <xi:include href="version-info.xml" xpointer="v256"/>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><option>--ssh-key-type=</option><replaceable>TYPE</replaceable></term>
+
+          <listitem><para>Configures the type of SSH key to generate, see
+          <citerefentry><refentrytitle>ssh-keygen</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+          for more information.</para>
+
+          <para>By default <literal>ed25519</literal> keys are generated, however <literal>rsa</literal> keys
+          may also be useful if the VM has a particularly old version of <command>sshd</command></para>.
+
+          <xi:include href="version-info.xml" xpointer="v256"/>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect2>
 
           <para>In order to embed binary data into the credential data for <option>--set-credential=</option>,
           use C-style escaping (i.e. <literal>\n</literal> to embed a newline, or <literal>\x00</literal> to
           embed a <constant>NUL</constant> byte). Note that the invoking shell might already apply unescaping
-          once, hence this might require double escaping!.</para>
+          once, hence this might require double escaping!</para>
 
           <xi:include href="version-info.xml" xpointer="v255"/></listitem>
         </varlistentry>
index 2b29a99dc822a1fd1a9c8466a29a3b5e131dacce..a2641e851687690e1fca10791a2376f4566a49ce 100644 (file)
           <xi:include href="version-info.xml" xpointer="v236"/>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>SubType=</varname></term>
+          <listitem>
+            <para>A subtype of the network service as defined in the section 7.1 of <ulink
+            url="https://tools.ietf.org/html/rfc6763">RFC 6763</ulink>, e.g. <literal>_printer</literal>.
+            </para>
+
+          <xi:include href="version-info.xml" xpointer="v256"/>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>Port=</varname></term>
           <listitem>
index 472add2f98407329b755969fffd59ffec5b8d87c..e143aebb1bd39a59c384b074c602d9bf1768da89 100644 (file)
@@ -857,7 +857,7 @@ Table=1234</programlisting></para>
           <literal>ipv4</literal>, <literal>ipv6</literal>, <literal>both</literal>, or
           <literal>no</literal>. Defaults to <literal>no</literal>.</para>
           <para>Note. Any positive boolean values such as <literal>yes</literal> or
-          <literal>true</literal> are now deprecated. Please use one of the values in the above.</para>
+          <literal>true</literal> are now deprecated. Please use one of the values above.</para>
 
           <xi:include href="version-info.xml" xpointer="v219"/>
         </listitem>
@@ -3611,7 +3611,7 @@ Address=192.168.0.1/24
 Address=192.168.0.2/24
 [DHCPServer]
 ServerAddress=192.168.0.1/24</programlisting>
-          are equivalent to the following.
+          are equivalent to the following:
           <programlisting>[Network]
 DHCPServer=yes
 Address=192.168.0.2/24
@@ -3973,7 +3973,7 @@ ServerAddress=192.168.0.1/24</programlisting>
 
         <listitem><para>Takes a timespan. Configures the retransmit time, used by clients to retransmit Neighbor
         Solicitation messages on address resolution and the Neighbor Unreachability Detection algorithm.
-        An integer the default unit of seconds, in the range 0…4294967295 msec. Defaults to 0.</para>
+        An integer, the default unit is seconds, in the range 0…4294967295 msec. Defaults to 0.</para>
 
         <xi:include href="version-info.xml" xpointer="v255"/>
         </listitem>
@@ -4062,8 +4062,8 @@ ServerAddress=192.168.0.1/24</programlisting>
       <varlistentry>
         <term><varname>HomeAgent=</varname></term>
 
-        <listitem><para>Takes a boolean. Specifies that IPv6 router advertisements which indicates to hosts that
-        the router acts as a Home Agent and includes a Home Agent Option. Defaults to false. See
+        <listitem><para>Takes a boolean. Specifies that IPv6 router advertisements which indicate to hosts that
+        the router acts as a Home Agent and includes a Home Agent option. Defaults to false. See
         <ulink url="https://tools.ietf.org/html/rfc6275">RFC 6275</ulink> for further details.</para>
 
          <xi:include href="version-info.xml" xpointer="v255"/>
@@ -4073,7 +4073,7 @@ ServerAddress=192.168.0.1/24</programlisting>
       <varlistentry>
         <term><varname>HomeAgentLifetimeSec=</varname></term>
 
-        <listitem><para>Takes a timespan. Specifies the lifetime of the Home Agent. An integer the default unit of seconds,
+        <listitem><para>Takes a timespan. Specifies the lifetime of the Home Agent. An integer, the default unit is seconds,
         in the range 1…65535. Defaults to the value set to <varname>RouterLifetimeSec=</varname>.</para>
 
          <xi:include href="version-info.xml" xpointer="v255"/>
index 7655f2edfe12f10621b282cb9c27c18ad1833652..27ceb48652f4a61f25a1271f6e21646e51a16e3a 100644 (file)
@@ -95,7 +95,7 @@
         <term><filename>250-firmware-code-early.pcrlock</filename></term>
 
         <listitem><para>Firmware code measurements, as recorded to PCR 0 and 2, up to the separator
-        measurement (see <filename>400-secureboot-separator.pcrlock.</filename> below). May be generated via
+        measurement (see <filename>400-secureboot-separator.pcrlock</filename> below). May be generated via
         <command>systemd-pcrlock lock-firmware-code</command>.</para>
 
         <xi:include href="version-info.xml" xpointer="v255"/></listitem>
         <term><filename>250-firmware-config-early.pcrlock</filename></term>
 
         <listitem><para>Firmware configuration measurements, as recorded to PCR 1 and 3, up to the separator
-        measurement (see <filename>400-secureboot-separator.pcrlock.</filename> below). May be generated via
+        measurement (see <filename>400-secureboot-separator.pcrlock</filename> below). May be generated via
         <command>systemd-pcrlock lock-firmware-config</command>.</para>
 
         <xi:include href="version-info.xml" xpointer="v255"/></listitem>
         <term><filename>550-firmware-code-late.pcrlock</filename></term>
 
         <listitem><para>Firmware code measurements, as recorded to PCR 0 and 2, after the separator
-        measurement (see <filename>400-secureboot-separator.pcrlock.</filename> above). May be generated via
+        measurement (see <filename>400-secureboot-separator.pcrlock</filename> above). May be generated via
         <command>systemd-pcrlock lock-firmware-code</command>.</para>
 
         <xi:include href="version-info.xml" xpointer="v255"/></listitem>
         <term><filename>550-firmware-config-late.pcrlock</filename></term>
 
         <listitem><para>Firmware configuration measurements, as recorded to PCR 1 and 3, after the separator
-        measurement (see <filename>400-secureboot-separator.pcrlock.</filename> above). May be generated via
+        measurement (see <filename>400-secureboot-separator.pcrlock</filename> above). May be generated via
         <command>systemd-pcrlock lock-firmware-config</command>.</para>
 
         <xi:include href="version-info.xml" xpointer="v255"/></listitem>
         <term><filename>700-action-efi-exit-boot-services.pcrlock</filename></term>
 
         <listitem><para>The EFI action generated when <function>ExitBootServices()</function> is generated,
-        i.e. the UEFI environment is left and the OS takes over. Covers the PCR 5 measurement. Statically
+        i.e. when the UEFI environment is left and the OS takes over. Covers the PCR 5 measurement. Statically
         defined.</para>
 
         <xi:include href="version-info.xml" xpointer="v255"/></listitem>
index 154a7a2e66a06aa67b24e6bded5d8063bfc2970c..67a3930a28a578be78fb360cd5d3375802822033 100644 (file)
 
           <row>
             <entry><literal>:</literal></entry>
-            <entry>If the executable path is prefixed with <literal>:</literal>, environment variable substitution (as described by the "Command Lines" section below) is not applied.</entry>
+            <entry>If the executable path is prefixed with <literal>:</literal>, environment variable substitution (as described below this table) is not applied.</entry>
           </row>
 
           <row>
index 1ac97ae137b8bf1cb1ace963d6418b257f19037d..c7166e4f643bd5b082d673bd8b02771f88fa34f5 100644 (file)
         <replaceable>x</replaceable> on a port <replaceable>y</replaceable> address in the
         <constant>AF_VSOCK</constant> family.  The CID is a unique 32-bit integer identifier in
         <constant>AF_VSOCK</constant> analogous to an IP address.  Specifying the CID is optional, and may be
-        set to the empty string.</para>
+        set to the empty string. <literal>vsock</literal> may be replaced with
+        <literal>vsock-stream</literal>, <literal>vsock-dgram</literal> or <literal>vsock-seqpacket</literal>
+        to force usage of the corresponding socket type.</para>
 
         <para>Note that <constant>SOCK_SEQPACKET</constant> (i.e.
         <varname>ListenSequentialPacket=</varname>) is only available
index 988b7175ba8dd90ebd44074efa2ab896f7fc3cf9..5980a8f93041b45ae700493a46010c8a26973660 100644 (file)
@@ -83,6 +83,7 @@
     <filename>sockets.target</filename>,
     <filename>soft-reboot.target</filename>,
     <filename>sound.target</filename>,
+    <filename>ssh-access.target</filename>,
     <filename>storage-target-mode.target</filename>,
     <filename>suspend.target</filename>,
     <filename>swap.target</filename>,
             the <literal>$portmap</literal> facility.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><filename>ssh-access.target</filename></term>
+          <listitem>
+            <para>Service and socket units that provide remote SSH secure shell access to the local system
+            should pull in this unit and order themselves before this unit. It's supposed to act as a
+            milestone indicating if and when SSH access into the system is available. It should only become
+            active when an SSH port is bound for remote clients (i.e. if SSH is used as a local privilege
+            escalation mechanism, it should <emphasis>not</emphasis> involve this target unit), regardless of
+            the protocol choices, i.e. regardless if IPv4, IPv6 or <constant>AF_VSOCK</constant> is
+            used.</para>
+            <xi:include href="version-info.xml" xpointer="v256"/>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><filename>time-set.target</filename></term>
           <listitem>
index 960df97f0b358a1b861e988241f72767a3679901..cb798af34c0ec3b8a5c31c0211d3e6d0a92fde16 100644 (file)
   <refsect1>
     <title>Signals</title>
 
+    <para>The service listens to various UNIX process signals that can be used to request various actions
+    asynchronously. The signal handling is enabled very early during boot, before any further processes are
+    invoked. However, a supervising container manager or similar that intends to request these operations via
+    this mechanism must take into consideration that this functionality is not available during the earliest
+    initialization phase. An <function>sd_notify()</function> notification message carrying the
+    <varname>X_SYSTEMD_SIGNALS_LEVEL=2</varname> field is emitted once the signal handlers are enabled, see
+    below. This may be used to schedule submission of these signals correctly.</para>
+
     <variablelist>
       <varlistentry>
         <term><constant>SIGTERM</constant></term>
       <varlistentry>
         <term><varname>$NOTIFY_SOCKET</varname></term>
 
-        <listitem><para>Set by systemd for supervised processes for
-        status and start-up completion notification. See
-        <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
-        for more information.</para></listitem>
+        <listitem><para>Set by service manager for its services for status and readiness notifications. Also
+        consumed by service manager for notifying supervising container managers or service managers up the
+        stack about its own progress. See
+        <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> and the
+        relevant section below for more information.</para></listitem>
       </varlistentry>
     </variablelist>
 
   </refsect1>
 
   <refsect1>
-    <title>System credentials</title>
+    <title>System Credentials</title>
 
     <para>During initialization the service manager will import credentials from various sources into the
     system's set of credentials, which can then be propagated into services and consumed by
         <term><varname>vmm.notify_socket</varname></term>
         <listitem>
           <para>Contains a <constant>AF_VSOCK</constant> or <constant>AF_UNIX</constant> address where to
-          send a <constant>READY=1</constant> notification datagram when the system has finished booting. See
-          <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> for
-          more information. Note that in case the hypervisor does not support <constant>SOCK_DGRAM</constant>
-          over <constant>AF_VSOCK</constant>, <constant>SOCK_SEQPACKET</constant> will be tried instead. The
-          credential payload for <constant>AF_VSOCK</constant> should be in the form
-          <literal>vsock:CID:PORT</literal>.</para>
-
-          <para>This feature is useful for hypervisors/VMMs or other processes on the host to receive a
+          send a <constant>READY=1</constant> notification message when the service manager has completed
+          booting. See
+          <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> and
+          the next section for more information. Note that in case the hypervisor does not support
+          <constant>SOCK_DGRAM</constant> over <constant>AF_VSOCK</constant>,
+          <constant>SOCK_SEQPACKET</constant> will be tried instead. The credential payload for
+          <constant>AF_VSOCK</constant> should be a string in the form
+          <literal>vsock:CID:PORT</literal>. <literal>vsock-stream</literal>, <literal>vsock-dgram</literal>
+          and <literal>vsock-seqpacket</literal> can be used instead of <literal>vsock</literal> to force
+          usage of the corresponding socket type.</para>
+
+          <para>This feature is useful for machine managers or other processes on the host to receive a
           notification via VSOCK when a virtual machine has finished booting.</para>
 
           <xi:include href="version-info.xml" xpointer="v254"/>
         </listitem>
       </varlistentry>
     </variablelist>
+
+    <para>For a list of system credentials various other components of systemd consume, see
+    <citerefentry><refentrytitle>systemd.system-credentials</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Readiness Protocol</title>
+
+    <para>The service manager implements a readiness notification protocol both between the manager and its
+    services (i.e. down the stack), and between the manager and a potential supervisor further up the stack
+    (the latter could be a machine or container manager, or in case of a per-user service manager the system
+    service manager instance). The basic protocol (and the suggested API for it) is described in
+    <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
+
+    <para>The notification socket the service manager (including PID 1) uses for reporting readiness to its
+    own supervisor is set via the usual <varname>$NOTIFY_SOCKET</varname> environment variable (see
+    above). Since this is directly settable only for container managers and for the per-user instance of the
+    service manager, an additional mechanism to configure this is available, in particular intended for use
+    in VM environments: the <varname>vmm.notify_socket</varname> system credential (see above) may be set to
+    a suitable socket (typically an <constant>AF_VSOCK</constant> one) via SMBIOS Type 11 vendor strings. For
+    details see above.</para>
+
+    <para>The notification protocol from the service manager up the stack towards a supervisor supports a
+    number of extension fields that allow a supervisor to learn about specific properties of the system and
+    track its boot progress. Specifically the following fields are sent:</para>
+
+    <itemizedlist>
+      <listitem><para>An <varname>X_SYSTEMD_HOSTNAME=…</varname> message will be sent out once the initial
+      hostname for the system has been determined. Note that during later runtime the hostname might be
+      changed again programmatically, and (currently) no further notifications are sent out in that case.</para>
+
+      <xi:include href="version-info.xml" xpointer="v256"/></listitem>
+
+      <listitem><para>An <varname>X_SYSTEMD_MACHINE_ID=…</varname> message will be sent out once the machine
+      ID of the system has been determined. See
+      <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+      details.</para>
+
+      <xi:include href="version-info.xml" xpointer="v256"/></listitem>
+
+      <listitem><para>An <varname>X_SYSTEMD_SIGNALS_LEVEL=…</varname> message will be sent out once the
+      service manager installed the various UNIX process signal handlers described above. The field's value
+      is an unsigned integer formatted as decimal string, and indicates the supported UNIX process signal
+      feature level of the service manager. Currently, only a single feature level is defined:</para>
+
+      <itemizedlist>
+        <listitem><para><varname>X_SYSTEMD_SIGNALS_LEVEL=2</varname> covers the various UNIX process signals
+        documented above – which are a superset of those supported by the historical SysV init
+        system.</para></listitem>
+      </itemizedlist>
+
+      <para>Signals sent to PID 1 before this message is sent might not be handled correctly yet. A consumer
+      of these messages should parse the value as an unsigned integer indication the level of support. For
+      now only the mentioned level 2 is defined, but later on additional levels might be defined with higher
+      integers, that will implement a superset of the currently defined behaviour.</para>
+
+      <xi:include href="version-info.xml" xpointer="v256"/></listitem>
+
+      <listitem><para><varname>X_SYSTEMD_UNIT_ACTIVE=…</varname> and
+      <varname>X_SYSTEMD_UNIT_INACTIVE=…</varname> messages will be sent out for each target unit as it
+      becomes active or stops being active. This is useful to track boot progress and functionality. For
+      example, once the <filename>ssh-access.target</filename> unit is reported started SSH access is
+      typically available, see
+      <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
+      details.</para>
+
+      <xi:include href="version-info.xml" xpointer="v256"/></listitem>
+    </itemizedlist>
+
+    <para>Note that these extension fields are sent in addition to the regular <literal>READY=1</literal> and
+    <literal>RELOADING=1</literal> notifications.</para>
   </refsect1>
 
   <refsect1>
index 646fea0d2479c36e1c0b7457f4a43227aeec1dc4..22add03a9d5a964c0ff6cca4357c737f30116616 100644 (file)
@@ -50,7 +50,7 @@
       <arg choice="plain">call</arg>
       <arg choice="plain"><replaceable>ADDRESS</replaceable></arg>
       <arg choice="plain"><replaceable>METHOD</replaceable></arg>
-      <arg choice="opt"><replaceable>PARAMETERS</replaceable></arg>
+      <arg choice="opt"><replaceable>ARGUMENTS</replaceable></arg>
     </cmdsynopsis>
 
     <cmdsynopsis>
         <term><command>info</command> <replaceable>ADDRESS</replaceable></term>
 
         <listitem><para>Show brief information about the specified service, including vendor name and list of
-        implemented interfaces. Expects a service address in the formats described above.</para>
+        implemented interfaces. Expects a service address in one of the formats described above.</para>
 
         <xi:include href="version-info.xml" xpointer="v255"/></listitem>
       </varlistentry>
         <term><command>list-interfaces</command> <replaceable>ADDRESS</replaceable></term>
 
         <listitem><para>Show list of interfaces implemented by the specified service. Expects a service
-        address in the formats described above.</para>
+        address in one of the formats described above.</para>
 
         <xi:include href="version-info.xml" xpointer="v255"/></listitem>
       </varlistentry>
         <term><command>introspect</command> <replaceable>ADDRESS</replaceable> <replaceable>INTERFACE</replaceable></term>
 
         <listitem><para>Show interface definition of the specified interface provided by the specified
-        service. Expects a service address in the formats described above and a Varlink interface
+        service. Expects a service address in one of the formats described above and a Varlink interface
         name.</para>
 
         <xi:include href="version-info.xml" xpointer="v255"/></listitem>
index 16f7491e0cbc840948b91b4dd59986913168d526..6bd09604b67eaa725c0284aee1bc0336761aed1f 100644 (file)
@@ -125,7 +125,7 @@ This is based on crypttab(5).
       <varlistentry>
         <term><option>uuid=<replaceable>UUID</replaceable></option></term>
 
-        <listitem><para>Use the provided <replaceable>UUID</replaceable> for format command instead of generating new one. The <replaceable>UUID</replaceable> must be
+        <listitem><para>Use the provided <replaceable>UUID</replaceable> instead of generating new one. The <replaceable>UUID</replaceable> must be
         provided in standard <acronym>UUID</acronym> format, e.g. <literal>12345678-1234-1234-1234-123456789abc</literal>.</para>
 
         <xi:include href="version-info.xml" xpointer="v254"/></listitem>
@@ -186,8 +186,8 @@ This is based on crypttab(5).
         <term><option>fec-device=<replaceable>PATH</replaceable></option></term>
 
         <listitem><para>Use forward error correction (<acronym>FEC</acronym>) to recover from corruption if hash verification fails. Use
-        encoding data from the specified device. The fec device argument can be block device or file image. For format,
-        if fec device path doesn't exist, it will be created as file. Note: block sizes for data and hash devices must
+        encoding data from the specified device. The fec device argument can be block device or file image.
+        If fec device path doesn't exist, it will be created as file. Note: block sizes for data and hash devices must
         match. Also, if the verity data_device is encrypted the fec_device should be too.</para>
 
         <xi:include href="version-info.xml" xpointer="v254"/></listitem>
index 078ba822ea15dbf259d3e48ee7af01cfae6b23c1..8d1cd8a9ed0ee7a0c153a941257ba975463fac64 100644 (file)
@@ -66,9 +66,9 @@ summary({'build mode' : get_option('mode')})
 #####################################################################
 
 # Try to install the git pre-commit hook
-add_git_hook_sh = find_program('tools/add-git-hook.sh', required : false)
-if add_git_hook_sh.found()
-        git_hook = run_command(add_git_hook_sh, check : false)
+git_setup_sh = find_program('tools/git-setup.sh', required : false)
+if git_setup_sh.found()
+        git_hook = run_command(git_setup_sh, check : false)
         if git_hook.returncode() == 0
                 message(git_hook.stdout().strip())
         endif
@@ -738,14 +738,15 @@ if not cc.has_header('sys/capability.h')
         error('POSIX caps headers not found')
 endif
 foreach header : ['crypt.h',
+                  'linux/ioprio.h',
                   'linux/memfd.h',
+                  'linux/time_types.h',
                   'linux/vm_sockets.h',
                   'sys/auxv.h',
+                  'sys/sdt.h',
                   'threads.h',
                   'valgrind/memcheck.h',
                   'valgrind/valgrind.h',
-                  'linux/time_types.h',
-                  'sys/sdt.h',
                  ]
 
         conf.set10('HAVE_' + header.underscorify().to_upper(),
index 19a3851fd132650920a2e65b032bd729a5eee77e..a5953d7613639eccf7c34ea3414c97d2f9015836 100644 (file)
@@ -41,3 +41,5 @@ KernelCommandLineExtra=systemd.crash_shell
                        enforcing=0
                        systemd.early_core_pattern=/core
                        systemd.firstboot=no
+                       systemd.setenv=SYSTEMD_ENABLE_LOG_CONTEXT=yes
+                       SYSTEMD_ENABLE_LOG_CONTEXT=yes
index fcefc3ead2bbf106cfd152f2f8a67a0164566178..aed8bb5ba8457901057560ca538493a3430a9edb 100644 (file)
@@ -31,6 +31,7 @@ Packages=
         kexec-tools
         kmod
         less
+        man
         mtools
         nano
         nftables
index aff566f94c24fb409cce0f334bff3b760bd5fda7..83887b1fba14a630d13f59d7c6fffc5337192e54 100755 (executable)
@@ -23,7 +23,7 @@ mount --mkdir --rbind "$PWD/pkg/$PKG_SUBDIR" "pkg/$PKG_SUBDIR/src/"
 # tmpfs during the build script so these changes don't end up in the image itself.
 tee --append /etc/makepkg.conf >/dev/null <<EOF
 CFLAGS="$CFLAGS -Og"
-OPTIONS=(!strip docs !libtool !staticlibs emptydirs !zipman purge debug !lto)
+OPTIONS=(!strip docs !libtool !staticlibs emptydirs !zipman purge !debug !lto)
 EOF
 
 # Linting the PKGBUILD takes multiple seconds every build so avoid that by nuking all the linting functions.
@@ -35,6 +35,10 @@ else
     TS="${SOURCE_DATE_EPOCH:-$(date +%s)}"
 fi
 
+sed --in-place "pkg/$PKG_SUBDIR/PKGBUILD" \
+    --expression "s/^_tag=.*/_tag=$(cat meson.version)/" \
+    --expression "s/^pkgrel=.*/pkgrel=$(date "+%Y%m%d%H%M%S" --date "@$TS")/"
+
 # We get around makepkg's root check by setting EUID to something else.
 # shellcheck disable=SC2046
 env --chdir="pkg/$PKG_SUBDIR" \
@@ -48,6 +52,4 @@ env --chdir="pkg/$PKG_SUBDIR" \
     BUILDDIR="$PWD/pkg/$PKG_SUBDIR" \
     PKGDEST="$PACKAGEDIR" \
     PKGEXT=".pkg.tar" \
-    PKGVER="$(cat meson.version)" \
-    PKGREL="$(date "+%Y%m%d%H%M%S" --date "@$TS")" \
     MESON_EXTRA_CONFIGURE_OPTIONS="-D mode=developer -D b_sanitize=${SANITIZERS:-none}"
index 4c80b0a36fd228e11a366d4c6188b27e1c850183..1cc7740194b858b53a2515ff3be1562883f726e0 100644 (file)
@@ -35,6 +35,7 @@ Packages=
         libasan
         libcap-ng-utils
         libubsan
+        man-db
         netcat
         openssh-clients
         openssh-server
index 47f3b7f488b9ebf81bca7ca10ab97b6e5f71766c..07c9b3a805c834552fc8afbc23ef157c53dfa766 100644 (file)
@@ -41,6 +41,7 @@ Packages=
         libcap-ng-utils
         libtss2-rc0
         libtss2-tcti-device0
+        man-db
         netcat-openbsd
         openssh-client
         openssh-server
index 6a60ce83e52c21e02bf84c06ddef30c715bb3352..562bebe08e855c2c960bbafc390c77925a1c1246 100755 (executable)
@@ -6,4 +6,4 @@ set -e
 # See https://github.com/openSUSE/suse-module-tools/pull/71
 rm -f "$BUILDROOT/usr/lib/modprobe.d/60-blacklist_fs-erofs.conf"
 
-mkosi-install systemd udev
+mkosi-install systemd udev systemd-experimental
index 63498c5098ed461633935fff811f9d3c072d17eb..45947a395b5371f2fe138422c74ed849077293ef 100644 (file)
@@ -39,6 +39,7 @@ Packages=
         openssh-clients
         openssh-server
         pam
+        python3-pefile
         quota
         rpm-build
         rsync
index 733045c8f6b0acf2f0cfaac207500483a678f4d2..4d1ecb083589270e9137c8bd3838e6b73bfdbff7 160000 (submodule)
--- a/pkg/arch
+++ b/pkg/arch
@@ -1 +1 @@
-Subproject commit 733045c8f6b0acf2f0cfaac207500483a678f4d2
+Subproject commit 4d1ecb083589270e9137c8bd3838e6b73bfdbff7
index 5451923e3e7f5d6cc54f78a8b1d08317a42b4109..3b4728136724b960f453de26e59ee39061575a8f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5451923e3e7f5d6cc54f78a8b1d08317a42b4109
+Subproject commit 3b4728136724b960f453de26e59ee39061575a8f
index 2822a03dded26b9453bddbba7c6a152de8204aec..2e32a339a10caad9392a7049bccfd1c4cd7c24cc 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2822a03dded26b9453bddbba7c6a152de8204aec
+Subproject commit 2e32a339a10caad9392a7049bccfd1c4cd7c24cc
index 37aca188c2ef606319217b30ff8b0c66df6c60f1..af49127b4b18ee276af099c2144760c353c39646 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 37aca188c2ef606319217b30ff8b0c66df6c60f1
+Subproject commit af49127b4b18ee276af099c2144760c353c39646
index befe6a08c564f665965264d53be33d4800858b5d..84d56c8a2239b8665c3438e0475f5d1f6108944c 100644 (file)
@@ -1,3 +1,4 @@
+pkg/debian
 src/basic/parse-util.c
 src/boot/efi/addon.c
 src/boot/efi/boot.c
index b22bbd95d6b3cabeb49a345059c3c00b0a024e94..61a9610aa3afdba4ff5a8a4e55d358c9343c6e4e 100644 (file)
@@ -53,7 +53,7 @@ _portablectl() {
                 comps="default nonetwork strict trusted"
                 ;;
             --copy)
-                comps="copy symlink auto"
+                comps="copy symlink auto mixed"
                 ;;
             --host|-H)
                 comps=$(compgen -A hostname)
index 6ccc7bf000f19c45617861a9bb8b3f19535cd844..0d7e3d7a893c53cc66786dd19eedcd7281ef7fc8 100644 (file)
@@ -31,7 +31,7 @@ _systemd_cat() {
 
     local -A OPTS=(
         [STANDALONE]='-h --help --version'
-        [ARG]='-t --identifier -p --priority --stderr-priority --level-prefix'
+        [ARG]='-t --identifier -p --priority --stderr-priority --level-prefix --namespace'
     )
 
     _init_completion || return
@@ -47,6 +47,9 @@ _systemd_cat() {
             --level-prefix)
                 comps='yes no'
                 ;;
+            --namespace)
+                comps=$(journalctl --list-namespaces --output=cat 2>/dev/null)
+                ;;
         esac
         COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
         return 0
index 863631571efe168e775bdc2d064a66c5c2fd23c3..44476144c118493c677b96d7f98307324b5332ff 100644 (file)
@@ -19,6 +19,7 @@ case "$service" in
             {-t+,--identifier=}'[Set syslog identifier.]:syslog identifier:' \
             {-p+,--priority=}'[Set priority value.]:value:({0..7})' \
             '--level-prefix=[Control whether level prefix shall be parsed.]:boolean:(1 0)' \
+            '--namespace=[Connect to specified journal namespace.]:journal namespace:' \
             ':Message'
         ;;
     systemd-cgls)
index 37e9f28a584d8fb812d65ad75b3d51bc576e605a..6d313986bb961977901f22323275b4088a086445 100644 (file)
@@ -167,7 +167,7 @@ _udevadm_commands(){
         'test-builtin:test a built-in command'
         'verify:verify udev rules files'
         'wait:wait for devices or device symlinks being created'
-        'lock:lock a block device and run a comand'
+        'lock:lock a block device and run a command'
     )
 
     if ((CURRENT == 1)); then
index 030b206f1e0276c12e6b6c40097ce9540615a117..c1b35ba8525d7cee3d91dbbd98ea02c680597663 100644 (file)
@@ -215,20 +215,21 @@ static int assess_user(
                 uint64_t *ret_badness,
                 char **ret_description) {
 
-        _cleanup_free_ char *d = NULL;
+        const char *d;
         uint64_t b;
+        int r;
 
         assert(ret_badness);
         assert(ret_description);
 
         if (streq_ptr(info->user, NOBODY_USER_NAME)) {
-                d = strdup("Service runs under as '" NOBODY_USER_NAME "' user, which should not be used for services");
+                d = "Service runs under as '" NOBODY_USER_NAME "' user, which should not be used for services";
                 b = 9;
         } else if (info->dynamic_user && !STR_IN_SET(info->user, "0", "root")) {
-                d = strdup("Service runs under a transient non-root user identity");
+                d = "Service runs under a transient non-root user identity";
                 b = 0;
         } else if (info->user && !STR_IN_SET(info->user, "0", "root", "")) {
-                d = strdup("Service runs under a static non-root user identity");
+                d = "Service runs under a static non-root user identity";
                 b = 0;
         } else {
                 *ret_badness = 10;
@@ -236,12 +237,11 @@ static int assess_user(
                 return 0;
         }
 
-        if (!d)
-                return log_oom();
+        r = strdup_to(ret_description, d);
+        if (r < 0)
+                return r;
 
         *ret_badness = b;
-        *ret_description = TAKE_PTR(d);
-
         return 0;
 }
 
@@ -254,7 +254,6 @@ static int assess_protect_home(
 
         const char *description;
         uint64_t badness;
-        char *copy;
         int r;
 
         assert(ret_badness);
@@ -277,13 +276,11 @@ static int assess_protect_home(
                 description = "Service has no access to home directories";
         }
 
-        copy = strdup(description);
-        if (!copy)
-                return log_oom();
+        r = strdup_to(ret_description, description);
+        if (r < 0)
+                return r;
 
         *ret_badness = badness;
-        *ret_description = copy;
-
         return 0;
 }
 
@@ -296,7 +293,6 @@ static int assess_protect_system(
 
         const char *description;
         uint64_t badness;
-        char *copy;
         int r;
 
         assert(ret_badness);
@@ -319,13 +315,11 @@ static int assess_protect_system(
                 description = "Service has limited write access to the OS file hierarchy";
         }
 
-        copy = strdup(description);
-        if (!copy)
-                return log_oom();
+        r = strdup_to(ret_description, description);
+        if (r < 0)
+                return r;
 
         *ret_badness = badness;
-        *ret_description = copy;
-
         return 0;
 }
 
@@ -370,9 +364,9 @@ static int assess_umask(
                 uint64_t *ret_badness,
                 char **ret_description) {
 
-        char *copy = NULL;
         const char *d;
         uint64_t b;
+        int r;
 
         assert(ret_badness);
         assert(ret_description);
@@ -394,13 +388,11 @@ static int assess_umask(
                 b = 0;
         }
 
-        copy = strdup(d);
-        if (!copy)
-                return log_oom();
+        r = strdup_to(ret_description, d);
+        if (r < 0)
+                return r;
 
         *ret_badness = b;
-        *ret_description = copy;
-
         return 0;
 }
 
@@ -537,30 +529,30 @@ static int assess_system_call_architectures(
                 uint64_t *ret_badness,
                 char **ret_description) {
 
-        char *d;
+        const char *d;
         uint64_t b;
+        int r;
 
         assert(ret_badness);
         assert(ret_description);
 
         if (set_isempty(info->system_call_architectures)) {
                 b = 10;
-                d = strdup("Service may execute system calls with all ABIs");
+                d = "Service may execute system calls with all ABIs";
         } else if (set_contains(info->system_call_architectures, "native") &&
                    set_size(info->system_call_architectures) == 1) {
                 b = 0;
-                d = strdup("Service may execute system calls only with native ABI");
+                d = "Service may execute system calls only with native ABI";
         } else {
                 b = 8;
-                d = strdup("Service may execute system calls with multiple ABIs");
+                d = "Service may execute system calls with multiple ABIs";
         }
 
-        if (!d)
-                return log_oom();
+        r = strdup_to(ret_description, d);
+        if (r < 0)
+                return r;
 
         *ret_badness = b;
-        *ret_description = d;
-
         return 0;
 }
 
@@ -607,12 +599,12 @@ static int assess_system_call_filter(
         assert(a->parameter < _SYSCALL_FILTER_SET_MAX);
         const SyscallFilterSet *f = syscall_filter_sets + a->parameter;
 
-        _cleanup_free_ char *d = NULL;
+        char *d;
         uint64_t b;
         int r;
 
         if (!info->system_call_filter_allow_list && set_isempty(info->system_call_filter)) {
-                r = free_and_strdup(&d, "Service does not filter system calls");
+                r = strdup_to(&d, "Service does not filter system calls");
                 b = 10;
         } else {
                 bool bad;
@@ -649,8 +641,8 @@ static int assess_system_call_filter(
         if (r < 0)
                 return log_oom();
 
+        *ret_description = d;
         *ret_badness = b;
-        *ret_description = TAKE_PTR(d);
 
         return 0;
 }
@@ -664,36 +656,36 @@ static int assess_ip_address_allow(
                 uint64_t *ret_badness,
                 char **ret_description) {
 
-        char *d = NULL;
+        const char *d;
         uint64_t b;
+        int r;
 
         assert(info);
         assert(ret_badness);
         assert(ret_description);
 
         if (info->ip_filters_custom_ingress || info->ip_filters_custom_egress) {
-                d = strdup("Service defines custom ingress/egress IP filters with BPF programs");
+                d = "Service defines custom ingress/egress IP filters with BPF programs";
                 b = 0;
         } else if (!info->ip_address_deny_all) {
-                d = strdup("Service does not define an IP address allow list");
+                d = "Service does not define an IP address allow list";
                 b = 10;
         } else if (info->ip_address_allow_other) {
-                d = strdup("Service defines IP address allow list with non-localhost entries");
+                d = "Service defines IP address allow list with non-localhost entries";
                 b = 5;
         } else if (info->ip_address_allow_localhost) {
-                d = strdup("Service defines IP address allow list with only localhost entries");
+                d = "Service defines IP address allow list with only localhost entries";
                 b = 2;
         } else {
-                d = strdup("Service blocks all IP address ranges");
+                d = "Service blocks all IP address ranges";
                 b = 0;
         }
 
-        if (!d)
-                return log_oom();
+        r = strdup_to(ret_description, d);
+        if (r < 0)
+                return r;
 
         *ret_badness = b;
-        *ret_description = d;
-
         return 0;
 }
 
@@ -704,7 +696,7 @@ static int assess_device_allow(
                 uint64_t *ret_badness,
                 char **ret_description) {
 
-        char *d = NULL;
+        char *d;
         uint64_t b;
 
         assert(info);
@@ -2828,7 +2820,6 @@ static int analyze_security(sd_bus *bus,
 
                 for (;;) {
                         UnitInfo info;
-                        char *copy = NULL;
 
                         r = bus_parse_unit_info(reply, &info);
                         if (r < 0)
@@ -2842,12 +2833,11 @@ static int analyze_security(sd_bus *bus,
                         if (!GREEDY_REALLOC(list, n + 2))
                                 return log_oom();
 
-                        copy = strdup(info.id);
-                        if (!copy)
-                                return log_oom();
+                        r = strdup_to(&list[n], info.id);
+                        if (r < 0)
+                                return r;
 
-                        list[n++] = copy;
-                        list[n] = NULL;
+                        list[++n] = NULL;
                 }
 
                 strv_sort(list);
index 68b1584629219f274894c61d031a57246e19a417..6991460f86e65a0b7b9a30293f6c71bba8025da6 100644 (file)
@@ -135,7 +135,7 @@ int cg_read_event(
                 return r;
 
         for (const char *p = content;;) {
-                _cleanup_free_ char *line = NULL, *key = NULL, *val = NULL;
+                _cleanup_free_ char *line = NULL, *key = NULL;
                 const char *q;
 
                 r = extract_first_word(&p, &line, "\n", 0);
@@ -154,12 +154,7 @@ int cg_read_event(
                 if (!streq(key, event))
                         continue;
 
-                val = strdup(q);
-                if (!val)
-                        return -ENOMEM;
-
-                *ret = TAKE_PTR(val);
-                return 0;
+                return strdup_to(ret, q);
         }
 }
 
@@ -234,20 +229,13 @@ int cg_read_subgroup(DIR *d, char **ret) {
         assert(ret);
 
         FOREACH_DIRENT_ALL(de, d, return -errno) {
-                char *b;
-
                 if (de->d_type != DT_DIR)
                         continue;
 
                 if (dot_or_dot_dot(de->d_name))
                         continue;
 
-                b = strdup(de->d_name);
-                if (!b)
-                        return -ENOMEM;
-
-                *ret = b;
-                return 1;
+                return strdup_to_full(ret, de->d_name);
         }
 
         *ret = NULL;
@@ -1125,44 +1113,29 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **ret_cgroup) {
         if (r < 0)
                 return r;
 
-        if (c == raw)
+        if (c == raw) {
                 *ret_cgroup = TAKE_PTR(raw);
-        else {
-                char *n;
-
-                n = strdup(c);
-                if (!n)
-                        return -ENOMEM;
-
-                *ret_cgroup = n;
+                return 0;
         }
 
-        return 0;
+        return strdup_to(ret_cgroup, c);
 }
 
 int cg_path_decode_unit(const char *cgroup, char **ret_unit) {
-        char *c, *s;
-        size_t n;
-
         assert(cgroup);
         assert(ret_unit);
 
-        n = strcspn(cgroup, "/");
+        size_t n = strcspn(cgroup, "/");
         if (n < 3)
                 return -ENXIO;
 
-        c = strndupa_safe(cgroup, n);
+        char *c = strndupa_safe(cgroup, n);
         c = cg_unescape(c);
 
         if (!unit_name_is_valid(c, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
                 return -ENXIO;
 
-        s = strdup(c);
-        if (!s)
-                return -ENOMEM;
-
-        *ret_unit = s;
-        return 0;
+        return strdup_to(ret_unit, c);
 }
 
 static bool valid_slice_name(const char *p, size_t n) {
@@ -1467,17 +1440,10 @@ int cg_path_get_session(const char *path, char **ret_session) {
         if (!session_id_valid(start))
                 return -ENXIO;
 
-        if (ret_session) {
-                char *rr;
-
-                rr = strdup(start);
-                if (!rr)
-                        return -ENOMEM;
-
-                *ret_session = rr;
-        }
+        if (!ret_session)
+                return 0;
 
-        return 0;
+        return strdup_to(ret_session, start);
 }
 
 int cg_pid_get_session(pid_t pid, char **ret_session) {
@@ -1534,34 +1500,26 @@ int cg_path_get_slice(const char *p, char **ret_slice) {
         assert(p);
         assert(ret_slice);
 
-        /* Finds the right-most slice unit from the beginning, but
-         * stops before we come to the first non-slice unit. */
+        /* Finds the right-most slice unit from the beginning, but stops before we come to
+         * the first non-slice unit. */
 
         for (;;) {
-                size_t n;
-
-                p += strspn(p, "/");
+                const char *s;
+                int n;
 
-                n = strcspn(p, "/");
-                if (!valid_slice_name(p, n)) {
-
-                        if (!e) {
-                                char *s;
-
-                                s = strdup(SPECIAL_ROOT_SLICE);
-                                if (!s)
-                                        return -ENOMEM;
+                n = path_find_first_component(&p, /* accept_dot_dot = */ false, &s);
+                if (n < 0)
+                        return n;
+                if (!valid_slice_name(s, n))
+                        break;
 
-                                *ret_slice = s;
-                                return 0;
-                        }
+                e = s;
+        }
 
-                        return cg_path_decode_unit(e, ret_slice);
-                }
+        if (e)
+                return cg_path_decode_unit(e, ret_slice);
 
-                e = p;
-                p += n;
-        }
+        return strdup_to(ret_slice, SPECIAL_ROOT_SLICE);
 }
 
 int cg_pid_get_slice(pid_t pid, char **ret_slice) {
@@ -1714,15 +1672,8 @@ int cg_slice_to_path(const char *unit, char **ret) {
         assert(unit);
         assert(ret);
 
-        if (streq(unit, SPECIAL_ROOT_SLICE)) {
-                char *x;
-
-                x = strdup("");
-                if (!x)
-                        return -ENOMEM;
-                *ret = x;
-                return 0;
-        }
+        if (streq(unit, SPECIAL_ROOT_SLICE))
+                return strdup_to(ret, "");
 
         if (!unit_name_is_valid(unit, UNIT_NAME_PLAIN))
                 return -EINVAL;
index 9f5477e4f3fe45e1e18635b6edb8676a4a6da8a4..245dd0800ef74ce3abb9c6ad57f33cf53bae3005 100644 (file)
@@ -741,12 +741,7 @@ int chase_extract_filename(const char *path, const char *root, char **ret) {
                         return r;
         }
 
-        char *fname = strdup(".");
-        if (!fname)
-                return -ENOMEM;
-
-        *ret = fname;
-        return 0;
+        return strdup_to(ret, ".");
 }
 
 int chase_and_open(const char *path, const char *root, ChaseFlags chase_flags, int open_flags, char **ret_path) {
index f82e13bdb02875449bcf2ee7d5233bd8dbb94c2a..652740cea757a1a0944e908ee5da863e262e68e0 100644 (file)
@@ -58,21 +58,18 @@ int device_path_make_major_minor(mode_t mode, dev_t devnum, char **ret) {
 }
 
 int device_path_make_inaccessible(mode_t mode, char **ret) {
-        char *s;
+        const char *s;
 
         assert(ret);
 
         if (S_ISCHR(mode))
-                s = strdup("/run/systemd/inaccessible/chr");
+                s = "/run/systemd/inaccessible/chr";
         else if (S_ISBLK(mode))
-                s = strdup("/run/systemd/inaccessible/blk");
+                s = "/run/systemd/inaccessible/blk";
         else
                 return -ENODEV;
-        if (!s)
-                return -ENOMEM;
 
-        *ret = s;
-        return 0;
+        return strdup_to(ret, s);
 }
 
 int device_path_make_canonical(mode_t mode, dev_t devnum, char **ret) {
index 9011ae29a3a82d8bebf2b1f28a799e07c5a927de..fdc6c439bb85cb563080b0c7c2e947b77fb5a3a7 100644 (file)
@@ -398,16 +398,8 @@ int systemd_efi_options_variable(char **ret) {
 
         /* For testing purposes it is sometimes useful to be able to override this */
         e = secure_getenv("SYSTEMD_EFI_OPTIONS");
-        if (e) {
-                char *m;
-
-                m = strdup(e);
-                if (!m)
-                        return -ENOMEM;
-
-                *ret = m;
-                return 0;
-        }
+        if (e)
+                return strdup_to(ret, e);
 
         r = read_one_line_file(EFIVAR_CACHE_PATH(EFI_SYSTEMD_VARIABLE(SystemdOptions)), ret);
         if (r == -ENOENT)
index 3aadb4bfab99fb3944241c97cdd143ef9ac269b2..523378177fb7ecb6c84bd4c9b99659670bba5883 100644 (file)
@@ -1504,7 +1504,7 @@ int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret) {
 
 int read_stripped_line(FILE *f, size_t limit, char **ret) {
         _cleanup_free_ char *s = NULL;
-        int r;
+        int r, k;
 
         assert(f);
 
@@ -1513,23 +1513,17 @@ int read_stripped_line(FILE *f, size_t limit, char **ret) {
                 return r;
 
         if (ret) {
-                const char *p;
-
-                p = strstrip(s);
+                const char *p = strstrip(s);
                 if (p == s)
                         *ret = TAKE_PTR(s);
                 else {
-                        char *copy;
-
-                        copy = strdup(p);
-                        if (!copy)
-                                return -ENOMEM;
-
-                        *ret = copy;
+                        k = strdup_to(ret, p);
+                        if (k < 0)
+                                return k;
                 }
         }
 
-        return r;
+        return r > 0;          /* Return 1 if something was read. */
 }
 
 int safe_fgetc(FILE *f, char *ret) {
index 94501853a158ac094784171f2974aaae73e42436..056c990cc77c966cc4b2fcd33355dffc64997f46 100644 (file)
@@ -25,7 +25,7 @@ int format_ifname_full(int ifindex, FormatIfnameFlag flag, char buf[static IF_NA
 }
 
 int format_ifname_full_alloc(int ifindex, FormatIfnameFlag flag, char **ret) {
-        char buf[IF_NAMESIZE], *copy;
+        char buf[IF_NAMESIZE];
         int r;
 
         assert(ret);
@@ -34,12 +34,7 @@ int format_ifname_full_alloc(int ifindex, FormatIfnameFlag flag, char **ret) {
         if (r < 0)
                 return r;
 
-        copy = strdup(buf);
-        if (!copy)
-                return -ENOMEM;
-
-        *ret = copy;
-        return 0;
+        return strdup_to(ret, buf);
 }
 
 char *format_bytes_full(char *buf, size_t l, uint64_t t, FormatBytesFlag flag) {
index 5bc7d2f95beb568c89c7dafe0d24c21739c9d3ba..7f0b5814be540189366bba72c97b5c496674c2da 100644 (file)
@@ -1236,3 +1236,99 @@ int xopenat_lock_full(
 
         return TAKE_FD(fd);
 }
+
+int link_fd(int fd, int newdirfd, const char *newpath) {
+        int r;
+
+        assert(fd >= 0);
+        assert(newdirfd >= 0 || newdirfd == AT_FDCWD);
+        assert(newpath);
+
+        /* Try linking via /proc/self/fd/ first. */
+        r = RET_NERRNO(linkat(AT_FDCWD, FORMAT_PROC_FD_PATH(fd), newdirfd, newpath, AT_SYMLINK_FOLLOW));
+        if (r != -ENOENT)
+                return r;
+
+        /* Fall back to symlinking via AT_EMPTY_PATH as fallback (this requires CAP_DAC_READ_SEARCH and a
+         * more recent kernel, but does not require /proc/ mounted) */
+        if (proc_mounted() != 0)
+                return r;
+
+        return RET_NERRNO(linkat(fd, "", newdirfd, newpath, AT_EMPTY_PATH));
+}
+
+int linkat_replace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
+        _cleanup_close_ int old_fd = -EBADF;
+        int r;
+
+        assert(olddirfd >= 0 || olddirfd == AT_FDCWD);
+        assert(newdirfd >= 0 || newdirfd == AT_FDCWD);
+        assert(!isempty(newpath)); /* source path is optional, but the target path is not */
+
+        /* Like linkat() but replaces the target if needed. Is a NOP if source and target already share the
+         * same inode. */
+
+        if (olddirfd == AT_FDCWD && isempty(oldpath)) /* Refuse operating on the cwd (which is a dir, and dirs can't be hardlinked) */
+                return -EISDIR;
+
+        if (path_implies_directory(oldpath)) /* Refuse these definite directories early */
+                return -EISDIR;
+
+        if (path_implies_directory(newpath))
+                return -EISDIR;
+
+        /* First, try to link this directly */
+        if (oldpath)
+                r = RET_NERRNO(linkat(olddirfd, oldpath, newdirfd, newpath, 0));
+        else
+                r = link_fd(olddirfd, newdirfd, newpath);
+        if (r >= 0)
+                return 0;
+        if (r != -EEXIST)
+                return r;
+
+        old_fd = xopenat(olddirfd, oldpath, O_PATH|O_CLOEXEC);
+        if (old_fd < 0)
+                return old_fd;
+
+        struct stat old_st;
+        if (fstat(old_fd, &old_st) < 0)
+                return -errno;
+
+        if (S_ISDIR(old_st.st_mode)) /* Don't bother if we are operating on a directory */
+                return -EISDIR;
+
+        struct stat new_st;
+        if (fstatat(newdirfd, newpath, &new_st, AT_SYMLINK_NOFOLLOW) < 0)
+                return -errno;
+
+        if (S_ISDIR(new_st.st_mode)) /* Refuse replacing directories */
+                return -EEXIST;
+
+        if (stat_inode_same(&old_st, &new_st)) /* Already the same inode? Then shortcut this */
+                return 0;
+
+        _cleanup_free_ char *tmp_path = NULL;
+        r = tempfn_random(newpath, /* extra= */ NULL, &tmp_path);
+        if (r < 0)
+                return r;
+
+        r = link_fd(old_fd, newdirfd, tmp_path);
+        if (r < 0) {
+                if (!ERRNO_IS_PRIVILEGE(r))
+                        return r;
+
+                /* If that didn't work due to permissions then go via the path of the dentry */
+                r = RET_NERRNO(linkat(olddirfd, oldpath, newdirfd, tmp_path, 0));
+                if (r < 0)
+                        return r;
+        }
+
+        r = RET_NERRNO(renameat(newdirfd, tmp_path, newdirfd, newpath));
+        if (r < 0) {
+                (void) unlinkat(newdirfd, tmp_path, /* flags= */ 0);
+                return r;
+        }
+
+        return 0;
+}
index 6a1e2e76d14929fc246d988e511c33d4ddd45b38..58a7d0a74595cfc3fd02ecefca5a80748688b29d 100644 (file)
@@ -146,3 +146,7 @@ int xopenat_lock_full(int dir_fd, const char *path, int open_flags, XOpenFlags x
 static inline int xopenat_lock(int dir_fd, const char *path, int open_flags, LockType locktype, int operation) {
         return xopenat_lock_full(dir_fd, path, open_flags, 0, 0, locktype, operation);
 }
+
+int link_fd(int fd, int newdirfd, const char *newpath);
+
+int linkat_replace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
index f134e7758965f5297f5dea018966391487ca3ac5..8b084a7c05f5acfc8d6bb6699cbd2b01927fab77 100644 (file)
@@ -28,3 +28,7 @@ int label_ops_post(int dir_fd, const char *path) {
 
         return label_ops->post(dir_fd, path);
 }
+
+void label_ops_reset(void) {
+        label_ops = NULL;
+}
index 9644e435a36fdb240cdae6e12197673fc0c5783a..a070bf28cc3344a7123f55aeeae0c22eda2f8d3e 100644 (file)
@@ -12,3 +12,4 @@ int label_ops_set(const LabelOps *label_ops);
 
 int label_ops_pre(int dir_fd, const char *path, mode_t mode);
 int label_ops_post(int dir_fd, const char *path);
+void label_ops_reset(void);
index 172a2c8ada086cbf4d3ea98c671c5b92ee4e5556..6faa6ad4fcef8de0e3f28211a388ded74f594d46 100644 (file)
@@ -49,6 +49,12 @@ static void *log_syntax_callback_userdata = NULL;
 
 static LogTarget log_target = LOG_TARGET_CONSOLE;
 static int log_max_level = LOG_INFO;
+static int log_target_max_level[] = {
+        [LOG_TARGET_CONSOLE] = INT_MAX,
+        [LOG_TARGET_KMSG]    = INT_MAX,
+        [LOG_TARGET_SYSLOG]  = INT_MAX,
+        [LOG_TARGET_JOURNAL] = INT_MAX,
+};
 static int log_facility = LOG_DAEMON;
 static bool ratelimit_kmsg = true;
 
@@ -439,6 +445,9 @@ static int write_to_console(
         if (console_fd < 0)
                 return 0;
 
+        if (LOG_PRI(level) > log_target_max_level[LOG_TARGET_CONSOLE])
+                return 0;
+
         if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
                 xsprintf(prefix, "<%i>", level);
                 iovec[n++] = IOVEC_MAKE_STRING(prefix);
@@ -523,6 +532,9 @@ static int write_to_syslog(
         if (syslog_fd < 0)
                 return 0;
 
+        if (LOG_PRI(level) > log_target_max_level[LOG_TARGET_SYSLOG])
+                return 0;
+
         xsprintf(header_priority, "<%i>", level);
 
         t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
@@ -592,6 +604,9 @@ static int write_to_kmsg(
         if (kmsg_fd < 0)
                 return 0;
 
+        if (LOG_PRI(level) > log_target_max_level[LOG_TARGET_KMSG])
+                return 0;
+
         if (ratelimit_kmsg && !ratelimit_below(&ratelimit)) {
                 if (ratelimit_num_dropped(&ratelimit) > 1)
                         return 0;
@@ -719,6 +734,9 @@ static int write_to_journal(
         if (journal_fd < 0)
                 return 0;
 
+        if (LOG_PRI(level) > log_target_max_level[LOG_TARGET_JOURNAL])
+                return 0;
+
         iovec_len = MIN(6 + _log_context_num_fields * 2, IOVEC_MAX);
         iovec = newa(struct iovec, iovec_len);
 
@@ -988,7 +1006,7 @@ void log_assert_failed_return(
 
         PROTECT_ERRNO;
         log_assert(LOG_DEBUG, text, file, line, func,
-                   "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
+                   "Assertion '%s' failed at %s:%u, function %s(), ignoring.");
 }
 
 int log_oom_internal(int level, const char *file, int line, const char *func) {
@@ -1218,11 +1236,74 @@ int log_set_target_from_string(const char *e) {
 int log_set_max_level_from_string(const char *e) {
         int r;
 
-        r = log_level_from_string(e);
+        for (;;) {
+                _cleanup_free_ char *word = NULL, *prefix = NULL;
+                LogTarget target;
+                const char *colon;
+
+                r = extract_first_word(&e, &word, ",", 0);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                colon = strchr(word, ':');
+                if (!colon) {
+                        r = log_level_from_string(word);
+                        if (r < 0)
+                                return r;
+
+                        log_set_max_level(r);
+                        continue;
+                }
+
+                prefix = strndup(word, colon - word);
+                if (!prefix)
+                        return -ENOMEM;
+
+                target = log_target_from_string(prefix);
+                if (target < 0)
+                        return target;
+
+                if (target >= _LOG_TARGET_SINGLE_MAX)
+                        return -EINVAL;
+
+                r = log_level_from_string(colon + 1);
+                if (r < 0)
+                        return r;
+
+                log_target_max_level[target] = r;
+        }
+
+        return 0;
+}
+
+int log_max_levels_to_string(int level, char **ret) {
+        _cleanup_free_ char *s = NULL;
+        int r;
+
+        assert(ret);
+
+        r = log_level_to_string_alloc(level, &s);
         if (r < 0)
                 return r;
 
-        log_set_max_level(r);
+        for (LogTarget target = 0; target < _LOG_TARGET_SINGLE_MAX; target++) {
+                _cleanup_free_ char *l = NULL;
+
+                if (log_target_max_level[target] == INT_MAX)
+                        continue;
+
+                r = log_level_to_string_alloc(log_target_max_level[target], &l);
+                if (r < 0)
+                        return r;
+
+                r = strextendf_with_separator(&s, ",", "%s:%s", log_target_to_string(target), l);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret = TAKE_PTR(s);
         return 0;
 }
 
@@ -1265,7 +1346,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
                         return 0;
 
                 if (log_set_target_from_string(value) < 0)
-                        log_warning("Failed to parse log target '%s'. Ignoring.", value);
+                        log_warning("Failed to parse log target '%s', ignoring.", value);
 
         } else if (proc_cmdline_key_streq(key, "systemd.log_level")) {
 
@@ -1273,32 +1354,32 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
                         return 0;
 
                 if (log_set_max_level_from_string(value) < 0)
-                        log_warning("Failed to parse log level '%s'. Ignoring.", value);
+                        log_warning("Failed to parse log level setting '%s', ignoring.", value);
 
         } else if (proc_cmdline_key_streq(key, "systemd.log_color")) {
 
                 if (log_show_color_from_string(value ?: "1") < 0)
-                        log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
+                        log_warning("Failed to parse log color setting '%s', ignoring.", value);
 
         } else if (proc_cmdline_key_streq(key, "systemd.log_location")) {
 
                 if (log_show_location_from_string(value ?: "1") < 0)
-                        log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
+                        log_warning("Failed to parse log location setting '%s', ignoring.", value);
 
         } else if (proc_cmdline_key_streq(key, "systemd.log_tid")) {
 
                 if (log_show_tid_from_string(value ?: "1") < 0)
-                        log_warning("Failed to parse log tid setting '%s'. Ignoring.", value);
+                        log_warning("Failed to parse log tid setting '%s', ignoring.", value);
 
         } else if (proc_cmdline_key_streq(key, "systemd.log_time")) {
 
                 if (log_show_time_from_string(value ?: "1") < 0)
-                        log_warning("Failed to parse log time setting '%s'. Ignoring.", value);
+                        log_warning("Failed to parse log time setting '%s', ignoring.", value);
 
         } else if (proc_cmdline_key_streq(key, "systemd.log_ratelimit_kmsg")) {
 
                 if (log_set_ratelimit_kmsg_from_string(value ?: "1") < 0)
-                        log_warning("Failed to parse log ratelimit kmsg boolean '%s'. Ignoring.", value);
+                        log_warning("Failed to parse log ratelimit kmsg boolean '%s', ignoring.", value);
         }
 
         return 0;
@@ -1318,31 +1399,31 @@ void log_parse_environment_variables(void) {
 
         e = getenv("SYSTEMD_LOG_TARGET");
         if (e && log_set_target_from_string(e) < 0)
-                log_warning("Failed to parse log target '%s'. Ignoring.", e);
+                log_warning("Failed to parse log target '%s', ignoring.", e);
 
         e = getenv("SYSTEMD_LOG_LEVEL");
         if (e && log_set_max_level_from_string(e) < 0)
-                log_warning("Failed to parse log level '%s'. Ignoring.", e);
+                log_warning("Failed to parse log level '%s', ignoring.", e);
 
         e = getenv("SYSTEMD_LOG_COLOR");
         if (e && log_show_color_from_string(e) < 0)
-                log_warning("Failed to parse log color '%s'. Ignoring.", e);
+                log_warning("Failed to parse log color '%s', ignoring.", e);
 
         e = getenv("SYSTEMD_LOG_LOCATION");
         if (e && log_show_location_from_string(e) < 0)
-                log_warning("Failed to parse log location '%s'. Ignoring.", e);
+                log_warning("Failed to parse log location '%s', ignoring.", e);
 
         e = getenv("SYSTEMD_LOG_TIME");
         if (e && log_show_time_from_string(e) < 0)
-                log_warning("Failed to parse log time '%s'. Ignoring.", e);
+                log_warning("Failed to parse log time '%s', ignoring.", e);
 
         e = getenv("SYSTEMD_LOG_TID");
         if (e && log_show_tid_from_string(e) < 0)
-                log_warning("Failed to parse log tid '%s'. Ignoring.", e);
+                log_warning("Failed to parse log tid '%s', ignoring.", e);
 
         e = getenv("SYSTEMD_LOG_RATELIMIT_KMSG");
         if (e && log_set_ratelimit_kmsg_from_string(e) < 0)
-                log_warning("Failed to parse log ratelimit kmsg boolean '%s'. Ignoring.", e);
+                log_warning("Failed to parse log ratelimit kmsg boolean '%s', ignoring.", e);
 }
 
 void log_parse_environment(void) {
index 23f54b88fb0189503094c0e2f8eb979fe5018a7f..fc80902c450e2d924d715b1a917b8537ab064cda 100644 (file)
@@ -18,15 +18,16 @@ struct signalfd_siginfo;
 
 typedef enum LogTarget{
         LOG_TARGET_CONSOLE,
-        LOG_TARGET_CONSOLE_PREFIXED,
         LOG_TARGET_KMSG,
         LOG_TARGET_JOURNAL,
-        LOG_TARGET_JOURNAL_OR_KMSG,
         LOG_TARGET_SYSLOG,
+        LOG_TARGET_CONSOLE_PREFIXED,
+        LOG_TARGET_JOURNAL_OR_KMSG,
         LOG_TARGET_SYSLOG_OR_KMSG,
         LOG_TARGET_AUTO, /* console if stderr is not journal, JOURNAL_OR_KMSG otherwise */
         LOG_TARGET_NULL,
-        _LOG_TARGET_MAX,
+        _LOG_TARGET_SINGLE_MAX = LOG_TARGET_SYSLOG + 1,
+        _LOG_TARGET_MAX = LOG_TARGET_NULL + 1,
         _LOG_TARGET_INVALID = -EINVAL,
 } LogTarget;
 
@@ -59,6 +60,7 @@ void log_settle_target(void);
 void log_set_max_level(int level);
 int log_set_max_level_from_string(const char *e);
 int log_get_max_level(void) _pure_;
+int log_max_levels_to_string(int level, char **ret);
 
 void log_set_facility(int facility);
 
index fe78363b8615c9ccfa8e912c65681d861cccbaf5..d43c3cdd5ddde4cfd610773624003fc96a0704b1 100644 (file)
@@ -383,4 +383,17 @@ assert_cc(sizeof(dummy_t) == 0);
              ((long)(_current_ - _entries_) < (long)(ELEMENTSOF(_entries_) - 1)) && ({ entry = *_current_; true; }); \
              _current_++)
 
+#define DECIMAL_STR_FMT(x) _Generic((x),        \
+        char: "%c",                             \
+        bool: "%d",                             \
+        unsigned char: "%d",                    \
+        short: "%hd",                           \
+        unsigned short: "%hu",                  \
+        int: "%d",                              \
+        unsigned: "%u",                         \
+        long: "%ld",                            \
+        unsigned long: "%lu",                   \
+        long long: "%lld",                      \
+        unsigned long long: "%llu")
+
 #include "log.h"
index 62e3c292f531ef6dd733d17ee938d49f43e5aef9..3f72acf02f628ab08cc6d7273cffeda41b67f900 100644 (file)
@@ -4,21 +4,31 @@
 #include <linux/audit.h>
 
 #if HAVE_AUDIT
-#include <libaudit.h>
+#  include <libaudit.h>
 #endif
 
 #ifndef AUDIT_SERVICE_START
-#define AUDIT_SERVICE_START 1130 /* Service (daemon) start */
+#  define AUDIT_SERVICE_START 1130 /* Service (daemon) start */
+#else
+assert_cc(AUDIT_SERVICE_START == 1130);
 #endif
 
 #ifndef AUDIT_SERVICE_STOP
-#define AUDIT_SERVICE_STOP 1131 /* Service (daemon) stop */
+#  define AUDIT_SERVICE_STOP 1131 /* Service (daemon) stop */
+#else
+assert_cc(AUDIT_SERVICE_STOP == 1131);
 #endif
 
 #ifndef MAX_AUDIT_MESSAGE_LENGTH
-#define MAX_AUDIT_MESSAGE_LENGTH 8970
+#  define MAX_AUDIT_MESSAGE_LENGTH 8970
+#else
+assert_cc(MAX_AUDIT_MESSAGE_LENGTH == 8970);
 #endif
 
+/* Note: we check for AUDIT_NLGRP_MAX because it's a define, but we actually
+ * need AUDIT_NLGRP_READLOG which is an enum. */
 #ifndef AUDIT_NLGRP_MAX
-#define AUDIT_NLGRP_READLOG 1
+#  define AUDIT_NLGRP_READLOG 1
+#else
+assert_cc(AUDIT_NLGRP_READLOG == 1);
 #endif
index 5adda554e59aa539e0206024fcb99d24308f02af..c1c63a68292b1afa9f1d3b8f4b15abac6cee6d8a 100644 (file)
@@ -6,21 +6,29 @@
 /* 3a101b8de0d39403b2c7e5c23fd0b005668acf48 (3.16) */
 #ifndef CAP_AUDIT_READ
 #  define CAP_AUDIT_READ 37
+#else
+assert_cc(CAP_AUDIT_READ == 37);
 #endif
 
 /* 980737282232b752bb14dab96d77665c15889c36 (5.8) */
 #ifndef CAP_PERFMON
 #  define CAP_PERFMON 38
+#else
+assert_cc(CAP_PERFMON == 38);
 #endif
 
 /* a17b53c4a4b55ec322c132b6670743612229ee9c (5.8) */
 #ifndef CAP_BPF
 #  define CAP_BPF 39
+#else
+assert_cc(CAP_BPF == 39);
 #endif
 
 /* 124ea650d3072b005457faed69909221c2905a1f (5.9) */
 #ifndef CAP_CHECKPOINT_RESTORE
 #  define CAP_CHECKPOINT_RESTORE 40
+#else
+assert_cc(CAP_CHECKPOINT_RESTORE == 40);
 #endif
 
 #define SYSTEMD_CAP_LAST_CAP CAP_CHECKPOINT_RESTORE
@@ -34,6 +42,7 @@
 #    undef CAP_LAST_CAP
 #  endif
 #endif
+
 #ifndef CAP_LAST_CAP
 #  define CAP_LAST_CAP SYSTEMD_CAP_LAST_CAP
 #endif
index 0dec59114663a71de41b066d80f00dce7531ab0a..e4ca56f0b1b00ebfe5ef14f6c289004ed49464ae 100644 (file)
@@ -2,9 +2,9 @@
 #pragma once
 
 #ifndef DRM_IOCTL_SET_MASTER
-#define DRM_IOCTL_SET_MASTER _IO('d', 0x1e)
+#  define DRM_IOCTL_SET_MASTER _IO('d', 0x1e)
 #endif
 
 #ifndef DRM_IOCTL_DROP_MASTER
-#define DRM_IOCTL_DROP_MASTER _IO('d', 0x1f)
+#  define DRM_IOCTL_DROP_MASTER _IO('d', 0x1f)
 #endif
index 9b03bbac483e0dc3d0c9aa0d03329b4b5ab4cc91..ee70ae08dbcc4c02143976842267fd8dba57217c 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <linux/types.h>
 
+#include "macro.h"
+
 /* linux/fs.h */
 #ifndef RENAME_NOREPLACE /* 0a7c3937a1f23f8cb5fc77ae01661e9968a51d0c (3.15) */
 #define RENAME_NOREPLACE (1 << 0)
@@ -28,43 +30,63 @@ struct file_clone_range {
 
 /* linux/fs.h or sys/mount.h */
 #ifndef MS_MOVE
-#define MS_MOVE 8192
+#  define MS_MOVE 8192
+#else
+assert_cc(MS_MOVE == 8192);
 #endif
 
 #ifndef MS_REC
-#define MS_REC 16384
+#  define MS_REC 16384
+#else
+assert_cc(MS_REC == 16384);
 #endif
 
 #ifndef MS_PRIVATE
-#define MS_PRIVATE      (1<<18)
+#  define MS_PRIVATE      (1<<18)
+#else
+assert_cc(MS_PRIVATE == (1<<18));
 #endif
 
 #ifndef MS_SLAVE
-#define MS_SLAVE        (1<<19)
+#  define MS_SLAVE        (1<<19)
+#else
+assert_cc(MS_SLAVE == (1<<19));
 #endif
 
 #ifndef MS_SHARED
-#define MS_SHARED       (1<<20)
+#  define MS_SHARED       (1<<20)
+#else
+assert_cc(MS_SHARED == (1<<20));
 #endif
 
 #ifndef MS_RELATIME
-#define MS_RELATIME     (1<<21)
+#  define MS_RELATIME     (1<<21)
+#else
+assert_cc(MS_RELATIME == (1<<21));
 #endif
 
 #ifndef MS_KERNMOUNT
-#define MS_KERNMOUNT    (1<<22)
+#  define MS_KERNMOUNT    (1<<22)
+#else
+assert_cc(MS_KERNMOUNT == (1<<22));
 #endif
 
 #ifndef MS_I_VERSION
-#define MS_I_VERSION    (1<<23)
+#  define MS_I_VERSION    (1<<23)
+#else
+assert_cc(MS_I_VERSION == (1<<23));
 #endif
 
 #ifndef MS_STRICTATIME
-#define MS_STRICTATIME  (1<<24)
+#  define MS_STRICTATIME  (1<<24)
+#else
+assert_cc(MS_STRICTATIME == (1 << 24));
 #endif
 
 #ifndef MS_LAZYTIME
-#define MS_LAZYTIME     (1<<25)
+#  define MS_LAZYTIME     (1<<25)
+#else
+assert_cc(MS_LAZYTIME == (1<<25));
 #endif
 
 /* Not exposed yet. Defined at fs/ext4/ext4.h */
@@ -78,10 +100,14 @@ struct file_clone_range {
 #endif
 
 #ifndef FS_PROJINHERIT_FL
-#define FS_PROJINHERIT_FL 0x20000000
+#  define FS_PROJINHERIT_FL 0x20000000
+#else
+assert_cc(FS_PROJINHERIT_FL == 0x20000000);
 #endif
 
 /* linux/fscrypt.h */
 #ifndef FS_KEY_DESCRIPTOR_SIZE
-#define FS_KEY_DESCRIPTOR_SIZE 8
+#  define FS_KEY_DESCRIPTOR_SIZE 8
+#else
+assert_cc(FS_KEY_DESCRIPTOR_SIZE == 8);
 #endif
index 6cf16ffb97b65ff31793627a0e7b7866696993c2..ee61bf99d6a7320860281765878141e0ac93fad3 100644 (file)
@@ -4,9 +4,11 @@
 #include <linux/input.h>
 #include <linux/types.h>
 
+#include "macro.h"
+
 /* linux@c7dc65737c9a607d3e6f8478659876074ad129b8 (3.12) */
 #ifndef EVIOCREVOKE
-#define EVIOCREVOKE _IOW('E', 0x91, int)
+#  define EVIOCREVOKE _IOW('E', 0x91, int)
 #endif
 
 /* linux@06a16293f71927f756dcf37558a79c0b05a91641 (4.4) */
@@ -17,29 +19,40 @@ struct input_mask {
         __u64 codes_ptr;
 };
 
-#define EVIOCGMASK _IOR('E', 0x92, struct input_mask)
-#define EVIOCSMASK _IOW('E', 0x93, struct input_mask)
+#  define EVIOCGMASK _IOR('E', 0x92, struct input_mask)
+#  define EVIOCSMASK _IOW('E', 0x93, struct input_mask)
 #endif
 
 /* linux@7611392fe8ff95ecae528b01a815ae3d72ca6b95 (3.17) */
 #ifndef INPUT_PROP_POINTING_STICK
-#define INPUT_PROP_POINTING_STICK 0x05
+#  define INPUT_PROP_POINTING_STICK 0x05
+#else
+assert_cc(INPUT_PROP_POINTING_STICK == 0x05);
 #endif
 
 /* linux@500d4160abe9a2e88b12e319c13ae3ebd1e18108 (4.0) */
 #ifndef INPUT_PROP_ACCELEROMETER
-#define INPUT_PROP_ACCELEROMETER  0x06
+#  define INPUT_PROP_ACCELEROMETER  0x06
+#else
+assert_cc(INPUT_PROP_ACCELEROMETER == 0x06);
 #endif
 
 /* linux@d09bbfd2a8408a995419dff0d2ba906013cf4cc9 (3.11) */
 #ifndef BTN_DPAD_UP
-#define BTN_DPAD_UP    0x220
-#define BTN_DPAD_DOWN  0x221
-#define BTN_DPAD_LEFT  0x222
-#define BTN_DPAD_RIGHT 0x223
+#  define BTN_DPAD_UP    0x220
+#  define BTN_DPAD_DOWN  0x221
+#  define BTN_DPAD_LEFT  0x222
+#  define BTN_DPAD_RIGHT 0x223
+#else
+assert_cc(BTN_DPAD_UP    == 0x220);
+assert_cc(BTN_DPAD_DOWN  == 0x221);
+assert_cc(BTN_DPAD_LEFT  == 0x222);
+assert_cc(BTN_DPAD_RIGHT == 0x223);
 #endif
 
 /* linux@358f24704f2f016af7d504b357cdf32606091d07 (3.13) */
 #ifndef KEY_ALS_TOGGLE
-#define KEY_ALS_TOGGLE 0x230
+#  fine KEY_ALS_TOGGLE 0x230
+#else
+assert_cc(KEY_ALS_TOGGLE == 0x230);
 #endif
index 9cbd17279f20a1c569ee7e96f60ee6cccbfadaf2..13ce7928a740cfe3a0c8d8e709beec2672677260 100644 (file)
@@ -1,49 +1,81 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
-#include <sched.h>
+#if HAVE_LINUX_IOPRIO_H
+#  include <linux/ioprio.h>
+#endif
+
+#include "macro.h"
 
 /* Match values uses by the kernel internally, as no public header seems to exist. */
 
 #ifndef IOPRIO_N_CLASSES
 #  define IOPRIO_N_CLASSES 8
+#else
+assert_cc(IOPRIO_N_CLASSES == 8);
 #endif
 
 #ifndef IOPRIO_BE_NR
 #  define IOPRIO_BE_NR 8
+#else
+assert_cc(IOPRIO_BE_NR == 8);
 #endif
 
 #ifndef IOPRIO_CLASS_NONE
 #  define IOPRIO_CLASS_NONE 0
+#else
+assert_cc(IOPRIO_CLASS_NONE == 0);
 #endif
 #ifndef IOPRIO_CLASS_RT
 #  define IOPRIO_CLASS_RT   1
+#else
+assert_cc(IOPRIO_CLASS_RT == 1);
 #endif
 #ifndef IOPRIO_CLASS_BE
 #  define IOPRIO_CLASS_BE   2
+#else
+assert_cc(IOPRIO_CLASS_BE == 2);
 #endif
 #ifndef IOPRIO_CLASS_IDLE
 #  define IOPRIO_CLASS_IDLE 3
+#else
+assert_cc(IOPRIO_CLASS_IDLE == 3);
 #endif
 
 #ifndef IOPRIO_WHO_PROCESS
 #  define IOPRIO_WHO_PROCESS 1
+#else
+assert_cc(IOPRIO_WHO_PROCESS == 1);
 #endif
+
 #ifndef IOPRIO_WHO_PGRP
 #  define IOPRIO_WHO_PGRP    2
+#else
+assert_cc(IOPRIO_WHO_PGRP == 2);
 #endif
+
 #ifndef IOPRIO_WHO_USER
 #  define IOPRIO_WHO_USER    3
+#else
+assert_cc(IOPRIO_WHO_USER == 3);
 #endif
 
 #ifndef IOPRIO_BITS
 #  define IOPRIO_BITS        16
+#else
+assert_cc(IOPRIO_BITS == 16);
 #endif
+
 #ifndef IOPRIO_N_CLASSES
 #  define IOPRIO_N_CLASSES    8
+#else
+assert_cc(IOPRIO_N_CLASSES == 8);
 #endif
+
 #ifndef IOPRIO_CLASS_SHIFT
 #  define IOPRIO_CLASS_SHIFT 13
+#else
+assert_cc(IOPRIO_CLASS_SHIFT == 13);
 #endif
 
 static inline int ioprio_prio_class(int value) {
index 081003a65a9a28eb63a70f00ffb62bc1be02ec9a..78795fa352b51af75cd205990e0b548f60bc3255 100644 (file)
@@ -4,40 +4,60 @@
 #include <inttypes.h>
 #include <linux/keyctl.h>
 
+#include "macro.h"
+
 #ifndef KEYCTL_JOIN_SESSION_KEYRING
-#define KEYCTL_JOIN_SESSION_KEYRING 1
+#  define KEYCTL_JOIN_SESSION_KEYRING 1
+#else
+assert_cc(KEYCTL_JOIN_SESSION_KEYRING == 1);
 #endif
 
 #ifndef KEYCTL_CHOWN
-#define KEYCTL_CHOWN 4
+#  define KEYCTL_CHOWN 4
+#else
+assert_cc(KEYCTL_CHOWN == 4);
 #endif
 
 #ifndef KEYCTL_SETPERM
-#define KEYCTL_SETPERM 5
+#  define KEYCTL_SETPERM 5
+#else
+assert_cc(KEYCTL_SETPERM == 5);
 #endif
 
 #ifndef KEYCTL_DESCRIBE
-#define KEYCTL_DESCRIBE 6
+#  define KEYCTL_DESCRIBE 6
+#else
+assert_cc(KEYCTL_DESCRIBE == 6);
 #endif
 
 #ifndef KEYCTL_LINK
-#define KEYCTL_LINK 8
+#  define KEYCTL_LINK 8
+#else
+assert_cc(KEYCTL_LINK == 8);
 #endif
 
 #ifndef KEYCTL_READ
-#define KEYCTL_READ 11
+#  define KEYCTL_READ 11
+#else
+assert_cc(KEYCTL_READ == 11);
 #endif
 
 #ifndef KEYCTL_SET_TIMEOUT
-#define KEYCTL_SET_TIMEOUT 15
+#  define KEYCTL_SET_TIMEOUT 15
+#else
+assert_cc(KEYCTL_SET_TIMEOUT == 15);
 #endif
 
 #ifndef KEY_SPEC_USER_KEYRING
-#define KEY_SPEC_USER_KEYRING -4
+#  define KEY_SPEC_USER_KEYRING -4
+#else
+assert_cc(KEY_SPEC_USER_KEYRING == -4);
 #endif
 
 #ifndef KEY_SPEC_SESSION_KEYRING
-#define KEY_SPEC_SESSION_KEYRING -3
+#  define KEY_SPEC_SESSION_KEYRING -3
+#else
+assert_cc(KEY_SPEC_SESSION_KEYRING == -3);
 #endif
 
 /* From linux/key.h */
 
 typedef int32_t key_serial_t;
 
-#define KEY_POS_VIEW    0x01000000
-#define KEY_POS_READ    0x02000000
-#define KEY_POS_WRITE   0x04000000
-#define KEY_POS_SEARCH  0x08000000
-#define KEY_POS_LINK    0x10000000
-#define KEY_POS_SETATTR 0x20000000
-#define KEY_POS_ALL     0x3f000000
-
-#define KEY_USR_VIEW    0x00010000
-#define KEY_USR_READ    0x00020000
-#define KEY_USR_WRITE   0x00040000
-#define KEY_USR_SEARCH  0x00080000
-#define KEY_USR_LINK    0x00100000
-#define KEY_USR_SETATTR 0x00200000
-#define KEY_USR_ALL     0x003f0000
-
-#define KEY_GRP_VIEW    0x00000100
-#define KEY_GRP_READ    0x00000200
-#define KEY_GRP_WRITE   0x00000400
-#define KEY_GRP_SEARCH  0x00000800
-#define KEY_GRP_LINK    0x00001000
-#define KEY_GRP_SETATTR 0x00002000
-#define KEY_GRP_ALL     0x00003f00
-
-#define KEY_OTH_VIEW    0x00000001
-#define KEY_OTH_READ    0x00000002
-#define KEY_OTH_WRITE   0x00000004
-#define KEY_OTH_SEARCH  0x00000008
-#define KEY_OTH_LINK    0x00000010
-#define KEY_OTH_SETATTR 0x00000020
-#define KEY_OTH_ALL     0x0000003f
+#  define KEY_POS_VIEW    0x01000000
+#  define KEY_POS_READ    0x02000000
+#  define KEY_POS_WRITE   0x04000000
+#  define KEY_POS_SEARCH  0x08000000
+#  define KEY_POS_LINK    0x10000000
+#  define KEY_POS_SETATTR 0x20000000
+#  define KEY_POS_ALL     0x3f000000
+
+#  define KEY_USR_VIEW    0x00010000
+#  define KEY_USR_READ    0x00020000
+#  define KEY_USR_WRITE   0x00040000
+#  define KEY_USR_SEARCH  0x00080000
+#  define KEY_USR_LINK    0x00100000
+#  define KEY_USR_SETATTR 0x00200000
+#  define KEY_USR_ALL     0x003f0000
+
+#  define KEY_GRP_VIEW    0x00000100
+#  define KEY_GRP_READ    0x00000200
+#  define KEY_GRP_WRITE   0x00000400
+#  define KEY_GRP_SEARCH  0x00000800
+#  define KEY_GRP_LINK    0x00001000
+#  define KEY_GRP_SETATTR 0x00002000
+#  define KEY_GRP_ALL     0x00003f00
+
+#  define KEY_OTH_VIEW    0x00000001
+#  define KEY_OTH_READ    0x00000002
+#  define KEY_OTH_WRITE   0x00000004
+#  define KEY_OTH_SEARCH  0x00000008
+#  define KEY_OTH_LINK    0x00000010
+#  define KEY_OTH_SETATTR 0x00000020
+#  define KEY_OTH_ALL     0x0000003f
+#else
+assert_cc(KEY_OTH_ALL == 0x0000003f);
 #endif
index 7141544b64f0256915e30c2bb60313caa2edd5c3..c29082f519bb07965646e9ed8713d29daea1c975 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <linux/loop.h>
 
+#include "macro.h"
+
 #ifndef LOOP_CONFIGURE
 struct loop_config {
         __u32 fd;
@@ -11,14 +13,19 @@ struct loop_config {
         __u64 __reserved[8];
 };
 
-#define LOOP_CONFIGURE 0x4C0A
+#  define LOOP_CONFIGURE 0x4C0A
+#else
+assert_cc(LOOP_CONFIGURE == 0x4C0A);
 #endif
 
 #ifndef LO_FLAGS_DIRECT_IO
-#define LO_FLAGS_DIRECT_IO 16
-#define LOOP_SET_DIRECT_IO 0x4C08
+#  define LO_FLAGS_DIRECT_IO 16
+#  define LOOP_SET_DIRECT_IO 0x4C08
+#else
+assert_cc(LO_FLAGS_DIRECT_IO == 16);
+assert_cc(LO_FLAGS_DIRECT_IO == 0x4C08);
 #endif
 
 #ifndef LOOP_SET_STATUS_SETTABLE_FLAGS
-#define LOOP_SET_STATUS_SETTABLE_FLAGS (LO_FLAGS_AUTOCLEAR | LO_FLAGS_PARTSCAN | LO_FLAGS_DIRECT_IO)
+#  define LOOP_SET_STATUS_SETTABLE_FLAGS (LO_FLAGS_AUTOCLEAR | LO_FLAGS_PARTSCAN | LO_FLAGS_DIRECT_IO)
 #endif
index 82d71c8ad12337b3e64a25010ee8211fa93c2fd9..93a0d745772fca0a8e16852a11af69aff0117f56 100644 (file)
 
 /* 62aa81d7c4c24b90fdb61da70ac0dbbc414f9939 (4.13) */
 #ifndef OCFS2_SUPER_MAGIC
-#define OCFS2_SUPER_MAGIC 0x7461636f
+#  define OCFS2_SUPER_MAGIC 0x7461636f
+#else
+assert_cc(OCFS2_SUPER_MAGIC == 0x7461636f);
 #endif
 
 /* 67e9c74b8a873408c27ac9a8e4c1d1c8d72c93ff (4.5) */
 #ifndef CGROUP2_SUPER_MAGIC
-#define CGROUP2_SUPER_MAGIC 0x63677270
+#  define CGROUP2_SUPER_MAGIC 0x63677270
+#else
+assert_cc(CGROUP2_SUPER_MAGIC == 0x63677270);
 #endif
 
 /* 4282d60689d4f21b40692029080440cc58e8a17d (4.1) */
 #ifndef TRACEFS_MAGIC
-#define TRACEFS_MAGIC 0x74726163
+#  define TRACEFS_MAGIC 0x74726163
+#else
+assert_cc(TRACEFS_MAGIC == 0x74726163);
 #endif
 
 /* e149ed2b805fefdccf7ccdfc19eca22fdd4514ac (3.19) */
 #ifndef NSFS_MAGIC
-#define NSFS_MAGIC 0x6e736673
+#  define NSFS_MAGIC 0x6e736673
+#else
+assert_cc(NSFS_MAGIC == 0x6e736673);
 #endif
 
 /* b2197755b2633e164a439682fb05a9b5ea48f706 (4.4) */
 #ifndef BPF_FS_MAGIC
-#define BPF_FS_MAGIC 0xcafe4a11
+#  define BPF_FS_MAGIC 0xcafe4a11
+#else
+assert_cc(BPF_FS_MAGIC == 0xcafe4a11);
 #endif
 
 /* Not exposed yet (4.20). Defined at ipc/mqueue.c */
 #ifndef MQUEUE_MAGIC
-#define MQUEUE_MAGIC 0x19800202
+#  define MQUEUE_MAGIC 0x19800202
+#else
+assert_cc(MQUEUE_MAGIC == 0x19800202);
 #endif
 
 /* Not exposed yet (as of Linux 5.4). Defined in fs/xfs/libxfs/xfs_format.h */
 #ifndef XFS_SB_MAGIC
-#define XFS_SB_MAGIC 0x58465342
+#  define XFS_SB_MAGIC 0x58465342
+#else
+assert_cc(XFS_SB_MAGIC == 0x58465342);
 #endif
 
 /* dea2903719283c156b53741126228c4a1b40440f (5.17) */
 #ifndef CIFS_SUPER_MAGIC
-#define CIFS_SUPER_MAGIC 0xFF534D42
+#  define CIFS_SUPER_MAGIC 0xFF534D42
+#else
+assert_cc(CIFS_SUPER_MAGIC == 0xFF534D42);
 #endif
 
 /* dea2903719283c156b53741126228c4a1b40440f (5.17) */
 #ifndef SMB2_SUPER_MAGIC
-#define SMB2_SUPER_MAGIC 0xFE534D42
+#  define SMB2_SUPER_MAGIC 0xFE534D42
+#else
+assert_cc(SMB2_SUPER_MAGIC == 0xFE534D42);
 #endif
 
 /* 257f871993474e2bde6c497b54022c362cf398e1 (4.5) */
 #ifndef OVERLAYFS_SUPER_MAGIC
-#define OVERLAYFS_SUPER_MAGIC 0x794c7630
+#  define OVERLAYFS_SUPER_MAGIC 0x794c7630
+#else
+assert_cc(OVERLAYFS_SUPER_MAGIC == 0x794c7630);
 #endif
 
 /* 2a28900be20640fcd1e548b1e3bad79e8221fcf9 (4.7) */
 #ifndef UDF_SUPER_MAGIC
-#define UDF_SUPER_MAGIC 0x15013346
+#  define UDF_SUPER_MAGIC 0x15013346
+#else
+assert_cc(UDF_SUPER_MAGIC == 0x15013346);
 #endif
 
 /* b1123ea6d3b3da25af5c8a9d843bd07ab63213f4 (4.8) */
 #ifndef BALLOON_KVM_MAGIC
-#define BALLOON_KVM_MAGIC 0x13661366
+#  define BALLOON_KVM_MAGIC 0x13661366
+#else
+assert_cc(BALLOON_KVM_MAGIC == 0x13661366);
 #endif
 
 /* 48b4800a1c6af2cdda344ea4e2c843dcc1f6afc9 (4.8) */
 #ifndef ZSMALLOC_MAGIC
-#define ZSMALLOC_MAGIC 0x58295829
+#  define ZSMALLOC_MAGIC 0x58295829
+#else
+assert_cc(ZSMALLOC_MAGIC == 0x58295829);
 #endif
 
 /* 3bc52c45bac26bf7ed1dc8d287ad1aeaed1250b6 (4.9) */
 #ifndef DAXFS_MAGIC
-#define DAXFS_MAGIC 0x64646178
+#  define DAXFS_MAGIC 0x64646178
+#else
+assert_cc(DAXFS_MAGIC == 0x64646178);
 #endif
 
 /* 5ff193fbde20df5d80fec367cea3e7856c057320 (4.10) */
 #ifndef RDTGROUP_SUPER_MAGIC
-#define RDTGROUP_SUPER_MAGIC 0x7655821
+#  define RDTGROUP_SUPER_MAGIC 0x7655821
+#else
+assert_cc(RDTGROUP_SUPER_MAGIC == 0x7655821);
 #endif
 
 /* a481f4d917835cad86701fc0d1e620c74bb5cd5f (4.13) */
 #ifndef AAFS_MAGIC
-#define AAFS_MAGIC 0x5a3c69f0
+#  define AAFS_MAGIC 0x5a3c69f0
+#else
+assert_cc(AAFS_MAGIC == 0x5a3c69f0);
 #endif
 
 /* f044c8847bb61eff5e1e95b6f6bb950e7f4a73a4 (4.15) */
 #ifndef AFS_FS_MAGIC
-#define AFS_FS_MAGIC 0x6b414653
+#  define AFS_FS_MAGIC 0x6b414653
+#else
+assert_cc(AFS_FS_MAGIC == 0x6b414653);
 #endif
 
 /* dddde68b8f06dd83486124b8d245e7bfb15c185d (4.20) */
 #ifndef XFS_SUPER_MAGIC
-#define XFS_SUPER_MAGIC 0x58465342
+#  define XFS_SUPER_MAGIC 0x58465342
+#else
+assert_cc(XFS_SUPER_MAGIC == 0x58465342);
 #endif
 
 /* 3ad20fe393b31025bebfc2d76964561f65df48aa (5.0) */
 #ifndef BINDERFS_SUPER_MAGIC
-#define BINDERFS_SUPER_MAGIC 0x6c6f6f70
+#  define BINDERFS_SUPER_MAGIC 0x6c6f6f70
+#else
+assert_cc(BINDERFS_SUPER_MAGIC == 0x6c6f6f70);
 #endif
 
 /* ed63bb1d1f8469586006a9ca63c42344401aa2ab (5.3) */
 #ifndef DMA_BUF_MAGIC
-#define DMA_BUF_MAGIC 0x444d4142
+#  define DMA_BUF_MAGIC 0x444d4142
+#else
+assert_cc(DMA_BUF_MAGIC == 0x444d4142);
 #endif
 
 /* ea8157ab2ae5e914dd427e5cfab533b6da3819cd (5.3) */
 #ifndef Z3FOLD_MAGIC
-#define Z3FOLD_MAGIC 0x33
+#  define Z3FOLD_MAGIC 0x33
+#else
+assert_cc(Z3FOLD_MAGIC == 0x33);
 #endif
 
 /* 47e4937a4a7ca4184fd282791dfee76c6799966a (5.4) */
 #ifndef EROFS_SUPER_MAGIC_V1
-#define EROFS_SUPER_MAGIC_V1 0xe0f5e1e2
+#  define EROFS_SUPER_MAGIC_V1 0xe0f5e1e2
+#else
+assert_cc(EROFS_SUPER_MAGIC_V1 == 0xe0f5e1e2);
 #endif
 
 /* fe030c9b85e6783bc52fe86449c0a4b8aa16c753 (5.5) */
 #ifndef PPC_CMM_MAGIC
-#define PPC_CMM_MAGIC 0xc7571590
+#  define PPC_CMM_MAGIC 0xc7571590
+#else
+assert_cc(PPC_CMM_MAGIC == 0xc7571590);
 #endif
 
 /* 8dcc1a9d90c10fa4143e5c17821082e5e60e46a1 (5.6) */
 #ifndef ZONEFS_MAGIC
-#define ZONEFS_MAGIC 0x5a4f4653
+#  define ZONEFS_MAGIC 0x5a4f4653
+#else
+assert_cc(ZONEFS_MAGIC == 0x5a4f4653);
 #endif
 
 /* 3234ac664a870e6ea69ae3a57d824cd7edbeacc5 (5.8) */
 #ifndef DEVMEM_MAGIC
-#define DEVMEM_MAGIC 0x454d444d
+#  define DEVMEM_MAGIC 0x454d444d
+#else
+assert_cc(DEVMEM_MAGIC == 0x454d444d);
 #endif
 
 /* cb12fd8e0dabb9a1c8aef55a6a41e2c255fcdf4b (6.8) */
 #ifndef PID_FS_MAGIC
-#define PID_FS_MAGIC 0x50494446
+#  define PID_FS_MAGIC 0x50494446
+#else
+assert_cc(PID_FS_MAGIC == 0x50494446);
 #endif
 
 /* Not in mainline but included in Ubuntu */
 #ifndef SHIFTFS_MAGIC
-#define SHIFTFS_MAGIC 0x6a656a62
+#  define SHIFTFS_MAGIC 0x6a656a62
+#else
+assert_cc(SHIFTFS_MAGIC == 0x6a656a62);
 #endif
 
 /* 1507f51255c9ff07d75909a84e7c0d7f3c4b2f49 (5.14) */
 #ifndef SECRETMEM_MAGIC
-#define SECRETMEM_MAGIC 0x5345434d
+#  define SECRETMEM_MAGIC 0x5345434d
+#else
+assert_cc(SECRETMEM_MAGIC == 0x5345434d);
 #endif
 
 /* Not exposed yet. Defined at fs/fuse/inode.c */
 #ifndef FUSE_SUPER_MAGIC
-#define FUSE_SUPER_MAGIC 0x65735546
+#  define FUSE_SUPER_MAGIC 0x65735546
+#else
+assert_cc(FUSE_SUPER_MAGIC == 0x65735546);
 #endif
 
 /* Not exposed yet. Defined at fs/fuse/control.c */
 #ifndef FUSE_CTL_SUPER_MAGIC
-#define FUSE_CTL_SUPER_MAGIC 0x65735543
+#  define FUSE_CTL_SUPER_MAGIC 0x65735543
+#else
+assert_cc(FUSE_CTL_SUPER_MAGIC == 0x65735543);
 #endif
 
 /* Not exposed yet. Defined at fs/ceph/super.h */
 #ifndef CEPH_SUPER_MAGIC
-#define CEPH_SUPER_MAGIC 0x00c36400
+#  define CEPH_SUPER_MAGIC 0x00c36400
+#else
+assert_cc(CEPH_SUPER_MAGIC == 0x00c36400);
 #endif
 
 /* Not exposed yet. Defined at fs/orangefs/orangefs-kernel.h */
 #ifndef ORANGEFS_DEVREQ_MAGIC
-#define ORANGEFS_DEVREQ_MAGIC 0x20030529
+#  define ORANGEFS_DEVREQ_MAGIC 0x20030529
+#else
+assert_cc(ORANGEFS_DEVREQ_MAGIC == 0x20030529);
 #endif
 
 /* linux/gfs2_ondisk.h */
 #ifndef GFS2_MAGIC
-#define GFS2_MAGIC 0x01161970
+#  define GFS2_MAGIC 0x01161970
+#else
+assert_cc(GFS2_MAGIC == 0x01161970);
 #endif
 
 /* Not exposed yet. Defined at fs/configfs/mount.c */
 #ifndef CONFIGFS_MAGIC
-#define CONFIGFS_MAGIC 0x62656570
+#  define CONFIGFS_MAGIC 0x62656570
+#else
+assert_cc(CONFIGFS_MAGIC == 0x62656570);
 #endif
 
 /* Not exposed yet. Defined at fs/vboxsf/super.c */
 #ifndef VBOXSF_SUPER_MAGIC
-#define VBOXSF_SUPER_MAGIC 0x786f4256
+#  define VBOXSF_SUPER_MAGIC 0x786f4256
+#else
+assert_cc(VBOXSF_SUPER_MAGIC == 0x786f4256);
 #endif
 
 /* Not exposed yet. Defined at fs/exfat/exfat_fs.h */
 #ifndef EXFAT_SUPER_MAGIC
-#define EXFAT_SUPER_MAGIC 0x2011BAB0UL
+#  define EXFAT_SUPER_MAGIC 0x2011BAB0UL
+#else
+assert_cc(EXFAT_SUPER_MAGIC == 0x2011BAB0UL);
 #endif
 
 /* Not exposed yet, internally actually called RPCAUTH_GSSMAGIC. Defined in net/sunrpc/rpc_pipe.c */
 #ifndef RPC_PIPEFS_SUPER_MAGIC
-#define RPC_PIPEFS_SUPER_MAGIC 0x67596969
+#  define RPC_PIPEFS_SUPER_MAGIC 0x67596969
+#else
+assert_cc(RPC_PIPEFS_SUPER_MAGIC == 0x67596969);
 #endif
 
 /* Not exposed yet, defined at fs/ntfs/ntfs.h */
 #ifndef NTFS_SB_MAGIC
-#define NTFS_SB_MAGIC 0x5346544e
+#  define NTFS_SB_MAGIC 0x5346544e
+#else
+assert_cc(NTFS_SB_MAGIC == 0x5346544e);
 #endif
 
 /* Not exposed yet, encoded literally in fs/ntfs3/super.c. */
 #ifndef NTFS3_SUPER_MAGIC
-#define NTFS3_SUPER_MAGIC 0x7366746e
+#  define NTFS3_SUPER_MAGIC 0x7366746e
+#else
+assert_cc(NTFS3_SUPER_MAGIC == 0x7366746e);
 #endif
index f48c436dca287b43382663366d7f56be8a4e3f13..d6a8b4bb9e64ef9ac294f9a8070d95feb75eb1bc 100644 (file)
@@ -3,18 +3,28 @@
 
 #include <sys/mman.h>
 
+#include "macro.h"
+
 #ifndef MFD_ALLOW_SEALING
-#define MFD_ALLOW_SEALING 0x0002U
+#  define MFD_ALLOW_SEALING 0x0002U
+#else
+assert_cc(MFD_ALLOW_SEALING == 0x0002U);
 #endif
 
 #ifndef MFD_CLOEXEC
-#define MFD_CLOEXEC 0x0001U
+#  define MFD_CLOEXEC 0x0001U
+#else
+assert_cc(MFD_CLOEXEC == 0x0001U);
 #endif
 
 #ifndef MFD_NOEXEC_SEAL
-#define MFD_NOEXEC_SEAL 0x0008U
+#  define MFD_NOEXEC_SEAL 0x0008U
+#else
+assert_cc(MFD_NOEXEC_SEAL == 0x0008U);
 #endif
 
 #ifndef MFD_EXEC
-#define MFD_EXEC 0x0010U
+#  define MFD_EXEC 0x0010U
+#else
+assert_cc(MFD_EXEC == 0x0010U);
 #endif
index 69b0bcfcbfe65c44830fe12ab1acc7d7f6e611b1..d6e16e556e50935c6e92151e91bb6c69bd6491c1 100644 (file)
@@ -3,7 +3,11 @@
 
 #include <sys/mount.h>
 
+#include "macro.h"
+
 /* dab741e0e02bd3c4f5e2e97be74b39df2523fc6e (5.10) */
 #ifndef MS_NOSYMFOLLOW
-#define MS_NOSYMFOLLOW 256
+#  define MS_NOSYMFOLLOW 256
+#else
+assert_cc(MS_NOSYMFOLLOW == 256);
 #endif
index 7d9e395c921419e17a4833a86f93835ca83db641..2c9f9f6c50ffe00802f0f11cb0b9a31a3598ae66 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <linux/prctl.h>
 
+#include "macro.h"
+
 /* 58319057b7847667f0c9585b9de0e8932b0fdb08 (4.3) */
 #ifndef PR_CAP_AMBIENT
 #define PR_CAP_AMBIENT 47
 
 /* b507808ebce23561d4ff8c2aa1fb949fe402bc61 (6.3) */
 #ifndef PR_SET_MDWE
-#define PR_SET_MDWE 65
+#  define PR_SET_MDWE 65
+#else
+assert_cc(PR_SET_MDWE == 65);
 #endif
+
 #ifndef PR_MDWE_REFUSE_EXEC_GAIN
-#define PR_MDWE_REFUSE_EXEC_GAIN 1
+#  define PR_MDWE_REFUSE_EXEC_GAIN 1
+#else
+assert_cc(PR_MDWE_REFUSE_EXEC_GAIN == 1);
 #endif
 
 #ifndef PR_SET_MEMORY_MERGE
-#define PR_SET_MEMORY_MERGE 67
+#  define PR_SET_MEMORY_MERGE 67
+#else
+assert_cc(PR_SET_MEMORY_MERGE == 67);
 #endif
index 443b91368558934697d6d2832cd2346d8a81909d..0f8a5be0a233abdf8b5e0d0b0f3d77ec834d145a 100644 (file)
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include "macro.h"
+
 #if USE_SYS_RANDOM_H
 #  include <sys/random.h>
 #else
 #endif
 
 #ifndef GRND_NONBLOCK
-#define GRND_NONBLOCK 0x0001
+#  define GRND_NONBLOCK 0x0001
+#else
+assert_cc(GRND_NONBLOCK == 0x0001);
 #endif
 
 #ifndef GRND_RANDOM
-#define GRND_RANDOM 0x0002
+#  define GRND_RANDOM 0x0002
+#else
+assert_cc(GRND_RANDOM == 0x0002);
 #endif
 
 #ifndef GRND_INSECURE
-#define GRND_INSECURE 0x0004
+#  define GRND_INSECURE 0x0004
+#else
+assert_cc(GRND_INSECURE == 0x0004);
 #endif
index 6e7676527be8d344afbf2ff6aa4005fcb853bc7a..18076736c7f1a899c02013d48d8854f17eb758d3 100644 (file)
@@ -3,8 +3,12 @@
 
 #include <sys/resource.h>
 
+#include "macro.h"
+
 #ifndef RLIMIT_RTTIME
-#define RLIMIT_RTTIME 15
+#  define RLIMIT_RTTIME 15
+#else
+assert_cc(RLIMIT_RTTIME == 15);
 #endif
 
 /* If RLIMIT_RTTIME is not defined, then we cannot use RLIMIT_NLIMITS as is */
index bcd5b7712060188ba6f65d26dd7072ddc840579b..b8109d30ac60fd8e38a3a628c6a0739d3a3cb649 100644 (file)
@@ -3,24 +3,35 @@
 
 #include <sched.h>
 
+#include "macro.h"
+
 #ifndef CLONE_NEWCGROUP
-#define CLONE_NEWCGROUP 0x02000000
+#  define CLONE_NEWCGROUP 0x02000000
+#else
+assert_cc(CLONE_NEWCGROUP == 0x02000000);
 #endif
 
 /* 769071ac9f20b6a447410c7eaa55d1a5233ef40c (5.8) */
 #ifndef CLONE_NEWTIME
-#define CLONE_NEWTIME 0x00000080
+#  define CLONE_NEWTIME 0x00000080
+#else
+assert_cc(CLONE_NEWTIME == 0x00000080);
 #endif
 
 /* Not exposed yet. Defined at include/linux/sched.h */
 #ifndef PF_KTHREAD
-#define PF_KTHREAD 0x00200000
+#  define PF_KTHREAD 0x00200000
+#else
+assert_cc(PF_KTHREAD == 0x00200000);
 #endif
 
-/* The maximum thread/process name length including trailing NUL byte. This mimics the kernel definition of the same
- * name, which we need in userspace at various places but is not defined in userspace currently, neither under this
- * name nor any other. */
-/* Not exposed yet. Defined at include/linux/sched.h */
+/* The maximum thread/process name length including trailing NUL byte. This mimics the kernel definition of
+ * the same name, which we need in userspace at various places but is not defined in userspace currently,
+ * neither under this name nor any other.
+ *
+ * Not exposed yet. Defined at include/linux/sched.h */
 #ifndef TASK_COMM_LEN
-#define TASK_COMM_LEN 16
+#  define TASK_COMM_LEN 16
+#else
+assert_cc(TASK_COMM_LEN == 16);
 #endif
index dba3043d2264f0e43cb1b42a224fcd0010e51a2f..a01a4eca3aa1248b42928c6c774f0c150c7b764c 100644 (file)
@@ -3,6 +3,10 @@
 
 #include <sys/timerfd.h>
 
+#include "macro.h"
+
 #ifndef TFD_TIMER_CANCEL_ON_SET
-#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
+#  define TFD_TIMER_CANCEL_ON_SET (1 << 1)
+#else
+assert_cc(TFD_TIMER_CANCEL_ON_SET == (1 << 1));
 #endif
index f6233090a905c195b104196e1402359d745f8733..1d17705c356b1b86ca249df3de1f20ee10596051 100644 (file)
@@ -4,9 +4,9 @@
 #include <uchar.h>
 
 #if !HAVE_CHAR32_T
-#define char32_t uint32_t
+#  define char32_t uint32_t
 #endif
 
 #if !HAVE_CHAR16_T
-#define char16_t uint16_t
+#  define char16_t uint16_t
 #endif
index a24779d977a879cfd93e4d9b1956f314103cf851..3965b5bdbfbc4debca48ad24ea6679d320699b42 100644 (file)
@@ -3,6 +3,10 @@
 
 #include <sys/wait.h>
 
+#include "macro.h"
+
 #ifndef P_PIDFD
-#define P_PIDFD 3
+#  define P_PIDFD 3
+#else
+assert_cc(P_PIDFD == 3);
 #endif
index 06fa219bd197552c8be61b07e3e9e789f016ce15..7097a2cc128da1eb5638e26ae1c9459e3d081977 100644 (file)
@@ -4,7 +4,21 @@
 #include "string-util.h"
 #include "strv.h"
 
+const char* nulstr_get(const char *nulstr, const char *needle) {
+        if (!nulstr)
+                return NULL;
+
+        NULSTR_FOREACH(i, nulstr)
+                if (streq(i, needle))
+                        return i;
+
+        return NULL;
+}
+
 char** strv_parse_nulstr_full(const char *s, size_t l, bool drop_trailing_nuls) {
+        _cleanup_strv_free_ char **v = NULL;
+        size_t c = 0, i = 0;
+
         /* l is the length of the input data, which will be split at NULs into elements of the resulting
          * strv. Hence, the number of items in the resulting strv will be equal to one plus the number of NUL
          * bytes in the l bytes starting at s, unless s[l-1] is NUL, in which case the final empty string is
@@ -13,9 +27,6 @@ char** strv_parse_nulstr_full(const char *s, size_t l, bool drop_trailing_nuls)
          * Note that contrary to a normal nulstr which cannot contain empty strings, because the input data
          * is terminated by any two consequent NUL bytes, this parser accepts empty strings in s. */
 
-        _cleanup_strv_free_ char **v = NULL;
-        size_t c = 0, i = 0;
-
         assert(s || l <= 0);
 
         if (drop_trailing_nuls)
@@ -36,7 +47,7 @@ char** strv_parse_nulstr_full(const char *s, size_t l, bool drop_trailing_nuls)
         if (!v)
                 return NULL;
 
-        for (const char *p = s; p < s + l; ) {
+        for (const char *p = s; p < s + l;) {
                 const char *e;
 
                 e = memchr(p, 0, s + l - p);
@@ -44,7 +55,6 @@ char** strv_parse_nulstr_full(const char *s, size_t l, bool drop_trailing_nuls)
                 v[i] = memdup_suffix0(p, e ? e - p : s + l - p);
                 if (!v[i])
                         return NULL;
-
                 i++;
 
                 if (!e)
@@ -74,6 +84,9 @@ char** strv_split_nulstr(const char *s) {
 }
 
 int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
+        _cleanup_free_ char *m = NULL;
+        size_t n = 0;
+
         /* Builds a nulstr and returns it together with the size. An extra NUL byte will be appended (⚠️ but
          * not included in the size! ⚠️). This is done so that the nulstr can be used both in
          * strv_parse_nulstr() and in NULSTR_FOREACH()/strv_split_nulstr() contexts, i.e. with and without a
@@ -84,21 +97,18 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
          * NUL bytes (which it will, if not empty). To ensure that this assumption *always* holds, we'll
          * return a buffer with two NUL bytes in that case, but return a size of zero. */
 
-        _cleanup_free_ char *m = NULL;
-        size_t n = 0;
-
         assert(ret);
 
         STRV_FOREACH(i, l) {
                 size_t z;
 
-                z = strlen(*i);
+                z = strlen(*i) + 1;
 
-                if (!GREEDY_REALLOC(m, n + z + 2))
+                if (!GREEDY_REALLOC(m, n + z + 1)) /* One extra NUL at the end as marker */
                         return -ENOMEM;
 
-                memcpy(m + n, *i, z + 1);
-                n += z + 1;
+                memcpy(m + n, *i, z);
+                n += z;
         }
 
         if (!m) {
@@ -109,7 +119,7 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
 
                 n = 0;
         } else
-                /* Make sure there is a second extra NUL at the end of resulting nulstr (not counted in return size) */
+                /* Extra NUL is not counted in size returned */
                 m[n] = '\0';
 
         *ret = TAKE_PTR(m);
@@ -132,14 +142,3 @@ int set_make_nulstr(Set *s, char **ret, size_t *ret_size) {
 
         return strv_make_nulstr(strv, ret, ret_size);
 }
-
-const char* nulstr_get(const char *nulstr, const char *needle) {
-        if (!nulstr)
-                return NULL;
-
-        NULSTR_FOREACH(i, nulstr)
-                if (streq(i, needle))
-                        return i;
-
-        return NULL;
-}
index d7bc5fd1ced9523ad8ce1bfc3d42136a19520237..d6f2f58e9fd5062f8bd5f8abef04570f37ff98bc 100644 (file)
@@ -15,7 +15,6 @@
         for (typeof(*(l)) *(i) = (l), *(j) = strchr((i), 0)+1; (i) && *(i); (i) = strchr((j), 0)+1, (j) = *(i) ? strchr((i), 0)+1 : (i))
 
 const char* nulstr_get(const char *nulstr, const char *needle);
-
 static inline bool nulstr_contains(const char *nulstr, const char *needle) {
         return nulstr_get(nulstr, needle);
 }
@@ -25,9 +24,6 @@ static inline char** strv_parse_nulstr(const char *s, size_t l) {
         return strv_parse_nulstr_full(s, l, false);
 }
 char** strv_split_nulstr(const char *s);
-int strv_make_nulstr(char * const *l, char **p, size_t *n);
-int set_make_nulstr(Set *s, char **ret, size_t *ret_size);
-
 static inline int strv_from_nulstr(char ***ret, const char *nulstr) {
         char **t;
 
@@ -40,3 +36,6 @@ static inline int strv_from_nulstr(char ***ret, const char *nulstr) {
         *ret = t;
         return 0;
 }
+
+int strv_make_nulstr(char * const *l, char **p, size_t *n);
+int set_make_nulstr(Set *s, char **ret, size_t *ret_size);
index e7fc4a7f06922d0be04210bc3577b8f5dcd14022..540256b73b84300e39db52bc81e5ffcebb01c370 100644 (file)
@@ -92,7 +92,6 @@ int xdg_user_data_dir(char **ret, const char *suffix) {
 }
 
 int runtime_directory(char **ret, RuntimeScope scope, const char *suffix) {
-        _cleanup_free_ char *d = NULL;
         int r;
 
         assert(ret);
@@ -106,26 +105,20 @@ int runtime_directory(char **ret, RuntimeScope scope, const char *suffix) {
          * Return value indicates whether the suffix was applied or not */
 
         const char *e = secure_getenv("RUNTIME_DIRECTORY");
-        if (e) {
-                d = strdup(e);
-                if (!d)
-                        return -ENOMEM;
-
-                *ret = TAKE_PTR(d);
-                return false;
-        }
+        if (e)
+                return strdup_to(ret, e);
 
         if (scope == RUNTIME_SCOPE_USER) {
-                r = xdg_user_runtime_dir(&d, suffix);
+                r = xdg_user_runtime_dir(ret, suffix);
                 if (r < 0)
                         return r;
         } else {
-                d = path_join("/run", suffix);
+                char *d = path_join("/run", suffix);
                 if (!d)
                         return -ENOMEM;
+                *ret = d;
         }
 
-        *ret = TAKE_PTR(d);
         return true;
 }
 
index 6810bf66aa32f8b7459fc8ab0c8f96fd4bf3e638..4d335c64eeda287fa27c1ae2fe8b608b42ccb6f7 100644 (file)
@@ -1094,7 +1094,6 @@ int path_extract_filename(const char *path, char **ret) {
 }
 
 int path_extract_directory(const char *path, char **ret) {
-        _cleanup_free_ char *a = NULL;
         const char *c, *next = NULL;
         int r;
 
@@ -1118,14 +1117,10 @@ int path_extract_directory(const char *path, char **ret) {
                 if (*path != '/') /* filename only */
                         return -EDESTADDRREQ;
 
-                a = strdup("/");
-                if (!a)
-                        return -ENOMEM;
-                *ret = TAKE_PTR(a);
-                return 0;
+                return strdup_to(ret, "/");
         }
 
-        a = strndup(path, next - path);
+        _cleanup_free_ char *a = strndup(path, next - path);
         if (!a)
                 return -ENOMEM;
 
@@ -1336,6 +1331,20 @@ bool dot_or_dot_dot(const char *path) {
         return path[2] == 0;
 }
 
+bool path_implies_directory(const char *path) {
+
+        /* Sometimes, if we look at a path we already know it must refer to a directory, because it is
+         * suffixed with a slash, or its last component is "." or ".." */
+
+        if (!path)
+                return false;
+
+        if (dot_or_dot_dot(path))
+                return true;
+
+        return ENDSWITH_SET(path, "/", "/.", "/..");
+}
+
 bool empty_or_root(const char *path) {
 
         /* For operations relative to some root directory, returns true if the specified root directory is
index 39b6714525e95d20170a32ae2c15760dcb752d25..47699e6414210e7efb2f9464068019664f5beda3 100644 (file)
@@ -76,6 +76,10 @@ char* path_extend_internal(char **x, ...);
 #define path_extend(x, ...) path_extend_internal(x, __VA_ARGS__, POINTER_MAX)
 #define path_join(...) path_extend_internal(NULL, __VA_ARGS__, POINTER_MAX)
 
+static inline char* skip_leading_slash(const char *p) {
+        return skip_leading_chars(p, "/");
+}
+
 typedef enum PathSimplifyFlags {
         PATH_SIMPLIFY_KEEP_TRAILING_SLASH = 1 << 0,
 } PathSimplifyFlags;
@@ -201,6 +205,8 @@ bool valid_device_allow_pattern(const char *path);
 
 bool dot_or_dot_dot(const char *path);
 
+bool path_implies_directory(const char *path);
+
 static inline const char *skip_dev_prefix(const char *p) {
         const char *e;
 
index 522d8de1f4fe65196f60ca81e74f70eace011337..ce1ba3a1eabe00a1485bf3a829cbe3fd2369759b 100644 (file)
@@ -116,16 +116,8 @@ int proc_cmdline(char **ret) {
 
         /* For testing purposes it is sometimes useful to be able to override what we consider /proc/cmdline to be */
         e = secure_getenv("SYSTEMD_PROC_CMDLINE");
-        if (e) {
-                char *m;
-
-                m = strdup(e);
-                if (!m)
-                        return -ENOMEM;
-
-                *ret = m;
-                return 0;
-        }
+        if (e)
+                return strdup_to(ret, e);
 
         if (detect_container() > 0)
                 return pid_get_cmdline(1, SIZE_MAX, 0, ret);
index 69635e65f81f9bb727e8de0f254441141c889a43..351b5e4095924fd4b63505c358940f91e8e839ca 100644 (file)
@@ -1022,7 +1022,6 @@ int kill_and_sigcont(pid_t pid, int sig) {
 
 int getenv_for_pid(pid_t pid, const char *field, char **ret) {
         _cleanup_fclose_ FILE *f = NULL;
-        char *value = NULL;
         const char *path;
         size_t sum = 0;
         int r;
@@ -1031,22 +1030,8 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) {
         assert(field);
         assert(ret);
 
-        if (pid == 0 || pid == getpid_cached()) {
-                const char *e;
-
-                e = getenv(field);
-                if (!e) {
-                        *ret = NULL;
-                        return 0;
-                }
-
-                value = strdup(e);
-                if (!value)
-                        return -ENOMEM;
-
-                *ret = value;
-                return 1;
-        }
+        if (pid == 0 || pid == getpid_cached())
+                return strdup_to_full(ret, getenv(field));
 
         if (!pid_is_valid(pid))
                 return -EINVAL;
@@ -1075,14 +1060,8 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) {
                 sum += r;
 
                 match = startswith(line, field);
-                if (match && *match == '=') {
-                        value = strdup(match + 1);
-                        if (!value)
-                                return -ENOMEM;
-
-                        *ret = value;
-                        return 1;
-                }
+                if (match && *match == '=')
+                        return strdup_to_full(ret, match + 1);
         }
 
         *ret = NULL;
index 68e6afc67fc162de913d66d5d668ab29288e20a4..5eb8e4c98855ba4585f22073064e0896e7b5ae86 100644 (file)
@@ -453,6 +453,7 @@ int sockaddr_pretty(
 
         assert(sa);
         assert(salen >= sizeof(sa->sa.sa_family));
+        assert(ret);
 
         switch (sa->sa.sa_family) {
 
@@ -634,6 +635,7 @@ int socknameinfo_pretty(const struct sockaddr *sa, socklen_t salen, char **ret)
 
         assert(sa);
         assert(salen > sizeof(sa_family_t));
+        assert(ret);
 
         r = getnameinfo(sa, salen, host, sizeof(host), /* service= */ NULL, /* service_len= */ 0, IDN_FLAGS);
         if (r != 0) {
@@ -647,15 +649,7 @@ int socknameinfo_pretty(const struct sockaddr *sa, socklen_t salen, char **ret)
                 return sockaddr_pretty(sa, salen, /* translate_ipv6= */ true, /* include_port= */ true, ret);
         }
 
-        if (ret) {
-                char *copy = strdup(host);
-                if (!copy)
-                        return -ENOMEM;
-
-                *ret = copy;
-        }
-
-        return 0;
+        return strdup_to(ret, host);
 }
 
 static const char* const netlink_family_table[] = {
index 4040b172268f8b02f7a506a843de2877dc6c81d0..c208d7c59dcd3d47522bfdcb350ba77d855dab12 100644 (file)
@@ -239,7 +239,7 @@ int null_or_empty_path_with_root(const char *fn, const char *root) {
         return null_or_empty(&st);
 }
 
-static int fd_is_read_only_fs(int fd) {
+int fd_is_read_only_fs(int fd) {
         struct statvfs st;
 
         assert(fd >= 0);
index 06bd9fdd97b7840c41328d1aeb0a05e6c367a5be..7556f8f59a6ff44afbe0942fc731b656b9c3fa44 100644 (file)
@@ -45,6 +45,7 @@ static inline int null_or_empty_path(const char *fn) {
         return null_or_empty_path_with_root(fn, NULL);
 }
 
+int fd_is_read_only_fs(int fd);
 int path_is_read_only_fs(const char *path);
 
 int inode_same_at(int fda, const char *filea, int fdb, const char *fileb, int flags);
index c1e7e6e62248b4cb371af8ced124890854150b56..7f6c87b4613fde9c2d04aeffe4a15a1a6f20905d 100644 (file)
@@ -1126,6 +1126,24 @@ int free_and_strndup(char **p, const char *s, size_t l) {
         return 1;
 }
 
+int strdup_to_full(char **ret, const char *src) {
+        if (!src) {
+                if (ret)
+                        *ret = NULL;
+
+                return 0;
+        } else {
+                if (ret) {
+                        char *t = strdup(src);
+                        if (!t)
+                                return -ENOMEM;
+                        *ret = t;
+                }
+
+                return 1;
+        }
+};
+
 bool string_is_safe(const char *p) {
         if (!p)
                 return false;
@@ -1235,36 +1253,15 @@ int string_extract_line(const char *s, size_t i, char **ret) {
                                         return -ENOMEM;
 
                                 *ret = m;
-                                return !isempty(q + 1); /* more coming? */
-                        } else {
-                                if (p == s)
-                                        *ret = NULL; /* Just use the input string */
-                                else {
-                                        char *m;
-
-                                        m = strdup(p);
-                                        if (!m)
-                                                return -ENOMEM;
-
-                                        *ret = m;
-                                }
-
-                                return 0; /* The end */
-                        }
+                                return !isempty(q + 1); /* More coming? */
+                        } else
+                                /* Tell the caller to use the input string if equal */
+                                return strdup_to(ret, p != s ? p : NULL);
                 }
 
-                if (!q) {
-                        char *m;
-
+                if (!q)
                         /* No more lines, return empty line */
-
-                        m = strdup("");
-                        if (!m)
-                                return -ENOMEM;
-
-                        *ret = m;
-                        return 0; /* The end */
-                }
+                        return strdup_to(ret, "");
 
                 p = q + 1;
                 c++;
index e162765aa7174a8113952e2b606b5c22b09cb482..a68f3c94abc4180601c885a8a28c43fc31f4217a 100644 (file)
@@ -224,6 +224,12 @@ static inline int free_and_strdup_warn(char **p, const char *s) {
 }
 int free_and_strndup(char **p, const char *s, size_t l);
 
+int strdup_to_full(char **ret, const char *src);
+static inline int strdup_to(char **ret, const char *src) {
+        int r = strdup_to_full(ASSERT_PTR(ret), src);
+        return r < 0 ? r : 0;  /* Suppress return value of 1. */
+}
+
 bool string_is_safe(const char *p) _pure_;
 
 DISABLE_WARNING_STRINGOP_TRUNCATION;
@@ -297,25 +303,4 @@ bool version_is_valid_versionspec(const char *s);
 
 ssize_t strlevenshtein(const char *x, const char *y);
 
-static inline int strdup_or_null(const char *s, char **ret) {
-        char *c;
-
-        assert(ret);
-
-        /* This is a lot like strdup(), but is happy with NULL strings, and does not treat that as error, but
-         * copies the NULL value. */
-
-        if (!s) {
-                *ret = NULL;
-                return 0;
-        }
-
-        c = strdup(s);
-        if (!c)
-                return -ENOMEM;
-
-        *ret = c;
-        return 1;
-}
-
 char *strrstr(const char *haystack, const char *needle);
index 8b5a9fa8c68ffbb266683ee95ffb1656858ee9e8..518412ec36d1d3df2600e04ecde046ea7ec1a360 100644 (file)
@@ -697,18 +697,10 @@ int vtnr_from_tty(const char *tty) {
                 tty = active;
         }
 
-        if (tty == active)
-                *ret = TAKE_PTR(active);
-        else {
-                char *tmp;
-
-                tmp = strdup(tty);
-                if (!tmp)
-                        return -ENOMEM;
-
-                *ret = tmp;
-        }
+        if (tty != active)
+                return strdup_to(ret, tty);
 
+        *ret = TAKE_PTR(active);
         return 0;
 }
 
@@ -988,7 +980,7 @@ bool on_tty(void) {
 }
 
 int getttyname_malloc(int fd, char **ret) {
-        char path[PATH_MAX], *c; /* PATH_MAX is counted *with* the trailing NUL byte */
+        char path[PATH_MAX]; /* PATH_MAX is counted *with* the trailing NUL byte */
         int r;
 
         assert(fd >= 0);
@@ -1001,12 +993,7 @@ int getttyname_malloc(int fd, char **ret) {
         if (r > 0)
                 return -r;
 
-        c = strdup(skip_dev_prefix(path));
-        if (!c)
-                return -ENOMEM;
-
-        *ret = c;
-        return 0;
+        return strdup_to(ret, skip_dev_prefix(path));
 }
 
 int getttyname_harder(int fd, char **ret) {
@@ -1111,13 +1098,9 @@ int get_ctty(pid_t pid, dev_t *ret_devnr, char **ret) {
                 return -EINVAL;
 
         if (ret) {
-                _cleanup_free_ char *b = NULL;
-
-                b = strdup(w);
-                if (!b)
-                        return -ENOMEM;
-
-                *ret = TAKE_PTR(b);
+                r = strdup_to(ret, w);
+                if (r < 0)
+                        return r;
         }
 
         if (ret_devnr)
index 2aed260526a66fed4ec6b4e00e9ee2245cf348e1..0f3175ef43f1282b0fa4a610f813758037b762cd 100644 (file)
@@ -197,7 +197,7 @@ static inline bool colors_enabled(void) {
         }
 
 static inline const char *ansi_underline(void) {
-        return underline_enabled() ? ANSI_UNDERLINE : ANSI_NORMAL;
+        return underline_enabled() ? ANSI_UNDERLINE : "";
 }
 
 static inline const char *ansi_add_underline(void) {
index 822d660fdada776cc0ad08aa9e85b67dbdc977f8..b94f37c31c31e45e7ee04f25fcd3c94c5e481b6f 100644 (file)
@@ -1606,38 +1606,24 @@ bool clock_supported(clockid_t clock) {
 
 int get_timezone(char **ret) {
         _cleanup_free_ char *t = NULL;
-        const char *e;
-        char *z;
         int r;
 
         assert(ret);
 
         r = readlink_malloc("/etc/localtime", &t);
-        if (r == -ENOENT) {
+        if (r == -ENOENT)
                 /* If the symlink does not exist, assume "UTC", like glibc does */
-                z = strdup("UTC");
-                if (!z)
-                        return -ENOMEM;
-
-                *ret = z;
-                return 0;
-        }
+                return strdup_to(ret, "UTC");
         if (r < 0)
-                return r; /* returns EINVAL if not a symlink */
+                return r; /* Return EINVAL if not a symlink */
 
-        e = PATH_STARTSWITH_SET(t, "/usr/share/zoneinfo/", "../usr/share/zoneinfo/");
+        const char *e = PATH_STARTSWITH_SET(t, "/usr/share/zoneinfo/", "../usr/share/zoneinfo/");
         if (!e)
                 return -EINVAL;
-
         if (!timezone_is_valid(e, LOG_DEBUG))
                 return -EINVAL;
 
-        z = strdup(e);
-        if (!z)
-                return -ENOMEM;
-
-        *ret = z;
-        return 0;
+        return strdup_to(ret, e);
 }
 
 time_t mktime_or_timegm(struct tm *tm, bool utc) {
index e77ca9424892d7a113b258c388a04edabfa9282e..3a3f7dcc0ff1c7b1e106b3b26d309a234a92c6b9 100644 (file)
@@ -330,28 +330,7 @@ int fopen_tmpfile_linkable(const char *target, int flags, char **ret_path, FILE
         return 0;
 }
 
-static int link_fd(int fd, int newdirfd, const char *newpath) {
-        int r;
-
-        assert(fd >= 0);
-        assert(newdirfd >= 0 || newdirfd == AT_FDCWD);
-        assert(newpath);
-
-        /* Try symlinking via /proc/fd/ first. */
-        r = RET_NERRNO(linkat(AT_FDCWD, FORMAT_PROC_FD_PATH(fd), newdirfd, newpath, AT_SYMLINK_FOLLOW));
-        if (r != -ENOENT)
-                return r;
-
-        /* Fall back to symlinking via AT_EMPTY_PATH as fallback (this requires CAP_DAC_READ_SEARCH and a
-         * more recent kernel, but does not require /proc/ mounted) */
-        if (proc_mounted() != 0)
-                return r;
-
-        return RET_NERRNO(linkat(fd, "", newdirfd, newpath, AT_EMPTY_PATH));
-}
-
 int link_tmpfile_at(int fd, int dir_fd, const char *path, const char *target, LinkTmpfileFlags flags) {
-        _cleanup_free_ char *tmp = NULL;
         int r;
 
         assert(fd >= 0);
@@ -370,33 +349,14 @@ int link_tmpfile_at(int fd, int dir_fd, const char *path, const char *target, Li
                         r = RET_NERRNO(renameat(dir_fd, path, dir_fd, target));
                 else
                         r = rename_noreplace(dir_fd, path, dir_fd, target);
-                if (r < 0)
-                        return r;
         } else {
-
-                r = link_fd(fd, dir_fd, target);
-                if (r != -EEXIST || !FLAGS_SET(flags, LINK_TMPFILE_REPLACE))
-                        return r;
-
-                /* So the target already exists and we were asked to replace it. That sucks a bit, since the kernel's
-                 * linkat() logic does not allow that. We work-around this by linking the file to a random name
-                 * first, and then renaming that to the final name. This reintroduces the race O_TMPFILE kinda is
-                 * trying to fix, but at least the vulnerability window (i.e. where the file is linked into the file
-                 * system under a temporary name) is very short. */
-
-                r = tempfn_random(target, NULL, &tmp);
-                if (r < 0)
-                        return r;
-
-                if (link_fd(fd, dir_fd, tmp) < 0)
-                        return -EEXIST; /* propagate original error */
-
-                r = RET_NERRNO(renameat(dir_fd, tmp, dir_fd, target));
-                if (r < 0) {
-                        (void) unlinkat(dir_fd, tmp, 0);
-                        return r;
-                }
+                if (FLAGS_SET(flags, LINK_TMPFILE_REPLACE))
+                        r = linkat_replace(fd, /* oldpath= */ NULL, dir_fd, target);
+                else
+                        r = link_fd(fd, dir_fd, target);
         }
+        if (r < 0)
+                return r;
 
         if (FLAGS_SET(flags, LINK_TMPFILE_SYNC)) {
                 r = fsync_full(fd);
index 06ed9054d0bed310a2ee470ebf705bb7bfa1f8a0..4e2f77c03dc28c094b0af7bace3efbff77d95c41 100644 (file)
@@ -793,19 +793,10 @@ int unit_name_mangle_with_suffix(
         return 1;
 
 good:
-        s = strdup(name);
-        if (!s)
-                return -ENOMEM;
-
-        *ret = TAKE_PTR(s);
-        return 0;
+        return strdup_to(ret, name);
 }
 
 int slice_build_parent_slice(const char *slice, char **ret) {
-        _cleanup_free_ char *s = NULL;
-        char *dash;
-        int r;
-
         assert(slice);
         assert(ret);
 
@@ -817,18 +808,16 @@ int slice_build_parent_slice(const char *slice, char **ret) {
                 return 0;
         }
 
-        s = strdup(slice);
+        _cleanup_free_ char *s = strdup(slice);
         if (!s)
                 return -ENOMEM;
 
-        dash = strrchr(s, '-');
-        if (dash)
-                strcpy(dash, ".slice");
-        else {
-                r = free_and_strdup(&s, SPECIAL_ROOT_SLICE);
-                if (r < 0)
-                        return r;
-        }
+        char *dash = strrchr(s, '-');
+        if (!dash)
+                return strdup_to_full(ret, SPECIAL_ROOT_SLICE);
+
+        /* We know that s ended with .slice before truncation, so we have enough space. */
+        strcpy(dash, ".slice");
 
         *ret = TAKE_PTR(s);
         return 1;
index 0c0b4f23c7709a170f0e315655180e8f39f55df4..07e4e306a3ea83fc269a66ee1e295ffa4b374ef2 100644 (file)
@@ -316,13 +316,6 @@ static int make_bad(const char *prefix, uint64_t done, const char *suffix, char
         return 0;
 }
 
-static const char *skip_slash(const char *path) {
-        assert(path);
-        assert(path[0] == '/');
-
-        return path + 1;
-}
-
 static int verb_status(int argc, char *argv[], void *userdata) {
         _cleanup_free_ char *path = NULL, *prefix = NULL, *suffix = NULL, *good = NULL, *bad = NULL;
         uint64_t left, done;
@@ -370,14 +363,14 @@ static int verb_status(int argc, char *argv[], void *userdata) {
                         return log_error_errno(errno, "Failed to open $BOOT partition '%s': %m", *p);
                 }
 
-                if (faccessat(fd, skip_slash(path), F_OK, 0) >= 0) {
+                if (faccessat(fd, skip_leading_slash(path), F_OK, 0) >= 0) {
                         puts("indeterminate");
                         return 0;
                 }
                 if (errno != ENOENT)
                         return log_error_errno(errno, "Failed to check if '%s' exists: %m", path);
 
-                if (faccessat(fd, skip_slash(good), F_OK, 0) >= 0) {
+                if (faccessat(fd, skip_leading_slash(good), F_OK, 0) >= 0) {
                         puts("good");
                         return 0;
                 }
@@ -385,7 +378,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
                 if (errno != ENOENT)
                         return log_error_errno(errno, "Failed to check if '%s' exists: %m", good);
 
-                if (faccessat(fd, skip_slash(bad), F_OK, 0) >= 0) {
+                if (faccessat(fd, skip_leading_slash(bad), F_OK, 0) >= 0) {
                         puts("bad");
                         return 0;
                 }
@@ -445,17 +438,17 @@ static int verb_set(int argc, char *argv[], void *userdata) {
                 if (fd < 0)
                         return log_error_errno(errno, "Failed to open $BOOT partition '%s': %m", *p);
 
-                r = rename_noreplace(fd, skip_slash(source1), fd, skip_slash(target));
+                r = rename_noreplace(fd, skip_leading_slash(source1), fd, skip_leading_slash(target));
                 if (r == -EEXIST)
                         goto exists;
                 if (r == -ENOENT) {
 
-                        r = rename_noreplace(fd, skip_slash(source2), fd, skip_slash(target));
+                        r = rename_noreplace(fd, skip_leading_slash(source2), fd, skip_leading_slash(target));
                         if (r == -EEXIST)
                                 goto exists;
                         if (r == -ENOENT) {
 
-                                if (faccessat(fd, skip_slash(target), F_OK, 0) >= 0) /* Hmm, if we can't find either source file, maybe the destination already exists? */
+                                if (faccessat(fd, skip_leading_slash(target), F_OK, 0) >= 0) /* Hmm, if we can't find either source file, maybe the destination already exists? */
                                         goto exists;
 
                                 if (errno != ENOENT)
@@ -474,7 +467,7 @@ static int verb_set(int argc, char *argv[], void *userdata) {
                         log_debug("Successfully renamed '%s' to '%s'.", source1, target);
 
                 /* First, fsync() the directory these files are located in */
-                r = fsync_parent_at(fd, skip_slash(target));
+                r = fsync_parent_at(fd, skip_leading_slash(target));
                 if (r < 0)
                         log_debug_errno(errno, "Failed to synchronize image directory, ignoring: %m");
 
index fbc5d105653cb61eb54936c4c5ec85a52a84a2b6..e8217c1836102750f3b7776e46a0f852e1df7a40 100644 (file)
@@ -140,6 +140,8 @@ typedef struct {
         GUID_DEF(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c)
 #define EFI_IMAGE_SECURITY_DATABASE_GUID \
         GUID_DEF(0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f)
+#define EFI_CUSTOM_MODE_ENABLE_GUID \
+        GUID_DEF(0xc076ec0c, 0x7028, 0x4399, 0xa0, 0x72, 0x71, 0xee, 0x5c, 0x44, 0x8b, 0x9f)
 
 #define EVT_TIMER                         0x80000000U
 #define EVT_RUNTIME                       0x40000000U
index f76d2f46d75ac907d44c60bd209a92ff628a8ddc..718c44b2a6d3124d3670abfaf8c73f2e09feb252 100644 (file)
@@ -32,10 +32,46 @@ SecureBootMode secure_boot_mode(void) {
         return decode_secure_boot_mode(secure, audit, deployed, setup);
 }
 
+/*
+ * Custom mode allows to change secure boot certificate databases db, dbx, KEK and PK without the variable
+ * updates being signed. When enrolling certificates to an unconfigured system (no PK present yet) writing
+ * db, dbx and KEK updates without signature works fine even in standard mode. Writing PK updates without
+ * signature requires custom mode in any case.
+ *
+ * Enabling custom mode works only if a user is physically present. Note that OVMF has a dummy
+ * implementation for the user presence check (there is no useful way to implement a presence check for a
+ * virtual machine).
+ *
+ * FYI: Your firmware setup utility might offers the option to enroll certificates from *.crt files
+ * (DER-encoded x509 certificates) on the ESP; that uses custom mode too. Your firmware setup might also
+ * offer the option to switch the system into custom mode for the next boot.
+ */
+static bool custom_mode_enabled(void) {
+        bool enabled = false;
+
+        (void) efivar_get_boolean_u8(MAKE_GUID_PTR(EFI_CUSTOM_MODE_ENABLE),
+                                     u"CustomMode", &enabled);
+        return enabled;
+}
+
+static EFI_STATUS set_custom_mode(bool enable) {
+        static char16_t name[] = u"CustomMode";
+        static uint32_t attr =
+                EFI_VARIABLE_NON_VOLATILE |
+                EFI_VARIABLE_BOOTSERVICE_ACCESS;
+        uint8_t mode = enable
+                ? 1   /* CUSTOM_SECURE_BOOT_MODE   */
+                : 0;  /* STANDARD_SECURE_BOOT_MODE */
+
+        return RT->SetVariable(name, MAKE_GUID_PTR(EFI_CUSTOM_MODE_ENABLE),
+                               attr, sizeof(mode), &mode);
+}
+
 EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force) {
         assert(root_dir);
         assert(path);
 
+        bool need_custom_mode = false;
         EFI_STATUS err;
 
         clear_screen(COLOR_NORMAL);
@@ -88,21 +124,47 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool
                 const char16_t *name;
                 const char16_t *filename;
                 const EFI_GUID vendor;
+                bool required;
                 char *buffer;
                 size_t size;
         } sb_vars[] = {
-                { u"db",  u"db.auth",  EFI_IMAGE_SECURITY_DATABASE_GUID, NULL, 0 },
-                { u"KEK", u"KEK.auth", EFI_GLOBAL_VARIABLE, NULL, 0 },
-                { u"PK",  u"PK.auth",  EFI_GLOBAL_VARIABLE, NULL, 0 },
+                { u"db",  u"db.auth",  EFI_IMAGE_SECURITY_DATABASE_GUID, true, NULL, 0 },
+                { u"dbx", u"dbx.auth", EFI_IMAGE_SECURITY_DATABASE_GUID, false, NULL, 0 },
+                { u"KEK", u"KEK.auth", EFI_GLOBAL_VARIABLE, true, NULL, 0 },
+                { u"PK",  u"PK.auth",  EFI_GLOBAL_VARIABLE, true, NULL, 0 },
         };
 
         /* Make sure all keys files exist before we start enrolling them by loading them from the disk first. */
         for (size_t i = 0; i < ELEMENTSOF(sb_vars); i++) {
                 err = file_read(dir, sb_vars[i].filename, 0, 0, &sb_vars[i].buffer, &sb_vars[i].size);
-                if (err != EFI_SUCCESS) {
+                if (err != EFI_SUCCESS && sb_vars[i].required) {
                         log_error_status(err, "Failed reading file %ls\\%ls: %m", path, sb_vars[i].filename);
                         goto out_deallocate;
                 }
+                if (streq16(sb_vars[i].name, u"PK") && sb_vars[i].size > 20) {
+                        assert(sb_vars[i].buffer);
+                        /*
+                         * The buffer should be EFI_TIME (16 bytes), followed by
+                         * EFI_VARIABLE_AUTHENTICATION_2 header.  First header field is the size.  If the
+                         * size covers only the header itself (8 bytes) plus the signature type guid (16
+                         * bytes), leaving no space for an actual signature, we can conclude that no
+                         * signature is present.
+                         */
+                        uint32_t *sigsize = (uint32_t*)(sb_vars[i].buffer + 16);
+                        if (*sigsize <= 24) {
+                                printf("PK is not signed (need custom mode).\n");
+                                need_custom_mode = true;
+                        }
+                }
+        }
+
+        if (need_custom_mode && !custom_mode_enabled()) {
+                err = set_custom_mode(/* enable */ true);
+                if (err != EFI_SUCCESS) {
+                        log_error_status(err, "Failed to enable custom mode: %m");
+                        goto out_deallocate;
+                }
+                printf("Custom mode enabled.\n");
         }
 
         for (size_t i = 0; i < ELEMENTSOF(sb_vars); i++) {
@@ -112,6 +174,8 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool
                         EFI_VARIABLE_RUNTIME_ACCESS |
                         EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
 
+                if (sb_vars[i].size == 0)
+                        continue;
                 err = efivar_set_raw(&sb_vars[i].vendor, sb_vars[i].name, sb_vars[i].buffer, sb_vars[i].size, sb_vars_opts);
                 if (err != EFI_SUCCESS) {
                         log_error_status(err, "Failed to write %ls secure boot variable: %m", sb_vars[i].name);
index 88a9f49b5fb2a4cc1700b93f4db0e10b1f491b9b..8c5a57588da5f0d12cc236e7255a3981ff9d9de6 100644 (file)
@@ -51,10 +51,8 @@ static void automount_stop_expire(Automount *a);
 static int automount_send_ready(Automount *a, Set *tokens, int status);
 
 static void automount_init(Unit *u) {
-        Automount *a = AUTOMOUNT(u);
+        Automount *a = ASSERT_PTR(AUTOMOUNT(u));
 
-        assert(a);
-        assert(u);
         assert(u->load_state == UNIT_STUB);
 
         a->pipe_fd = -EBADF;
@@ -88,9 +86,7 @@ static void unmount_autofs(Automount *a) {
 }
 
 static void automount_done(Unit *u) {
-        Automount *a = AUTOMOUNT(u);
-
-        assert(a);
+        Automount *a = ASSERT_PTR(AUTOMOUNT(u));
 
         unmount_autofs(a);
 
@@ -227,10 +223,9 @@ static int automount_add_extras(Automount *a) {
 }
 
 static int automount_load(Unit *u) {
-        Automount *a = AUTOMOUNT(u);
+        Automount *a = ASSERT_PTR(AUTOMOUNT(u));
         int r;
 
-        assert(u);
         assert(u->load_state == UNIT_STUB);
 
         /* Load a .automount file */
@@ -250,6 +245,7 @@ static int automount_load(Unit *u) {
 
 static void automount_set_state(Automount *a, AutomountState state) {
         AutomountState old_state;
+
         assert(a);
 
         if (a->state != state)
@@ -271,10 +267,9 @@ static void automount_set_state(Automount *a, AutomountState state) {
 }
 
 static int automount_coldplug(Unit *u) {
-        Automount *a = AUTOMOUNT(u);
+        Automount *a = ASSERT_PTR(AUTOMOUNT(u));
         int r;
 
-        assert(a);
         assert(a->state == AUTOMOUNT_DEAD);
 
         if (a->deserialized_state == a->state)
@@ -310,9 +305,7 @@ static int automount_coldplug(Unit *u) {
 }
 
 static void automount_dump(Unit *u, FILE *f, const char *prefix) {
-        Automount *a = AUTOMOUNT(u);
-
-        assert(a);
+        Automount *a = ASSERT_PTR(AUTOMOUNT(u));
 
         fprintf(f,
                 "%sAutomount State: %s\n"
@@ -478,30 +471,22 @@ static int automount_send_ready(Automount *a, Set *tokens, int status) {
         r = 0;
 
         /* Autofs thankfully does not hand out 0 as a token */
-        while ((token = PTR_TO_UINT(set_steal_first(tokens)))) {
-                int k;
-
+        while ((token = PTR_TO_UINT(set_steal_first(tokens))))
                 /* Autofs fun fact:
                  *
-                 * if you pass a positive status code here, kernels
-                 * prior to 4.12 will freeze! Yay! */
-
-                k = autofs_send_ready(UNIT(a)->manager->dev_autofs_fd,
-                                      ioctl_fd,
-                                      token,
-                                      status);
-                if (k < 0)
-                        r = k;
-        }
+                 * if you pass a positive status code here, kernels prior to 4.12 will freeze! Yay! */
+                RET_GATHER(r, autofs_send_ready(UNIT(a)->manager->dev_autofs_fd,
+                                                ioctl_fd,
+                                                token,
+                                                status));
 
         return r;
 }
 
 static void automount_trigger_notify(Unit *u, Unit *other) {
-        Automount *a = AUTOMOUNT(u);
+        Automount *a = ASSERT_PTR(AUTOMOUNT(u));
         int r;
 
-        assert(a);
         assert(other);
 
         /* Filter out invocations with bogus state */
@@ -697,11 +682,10 @@ static int asynchronous_expire(int dev_autofs_fd, int ioctl_fd) {
 }
 
 static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void *userdata) {
+        Automount *a = ASSERT_PTR(AUTOMOUNT(userdata));
         _cleanup_close_ int ioctl_fd = -EBADF;
-        Automount *a = AUTOMOUNT(userdata);
         int r;
 
-        assert(a);
         assert(source == a->expire_event_source);
 
         ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id);
@@ -815,10 +799,9 @@ fail:
 }
 
 static int automount_start(Unit *u) {
-        Automount *a = AUTOMOUNT(u);
+        Automount *a = ASSERT_PTR(AUTOMOUNT(u));
         int r;
 
-        assert(a);
         assert(IN_SET(a->state, AUTOMOUNT_DEAD, AUTOMOUNT_FAILED));
 
         if (path_is_mount_point(a->where) > 0)
@@ -838,9 +821,8 @@ static int automount_start(Unit *u) {
 }
 
 static int automount_stop(Unit *u) {
-        Automount *a = AUTOMOUNT(u);
+        Automount *a = ASSERT_PTR(AUTOMOUNT(u));
 
-        assert(a);
         assert(IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING));
 
         automount_enter_dead(a, AUTOMOUNT_SUCCESS);
@@ -848,11 +830,10 @@ static int automount_stop(Unit *u) {
 }
 
 static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
-        Automount *a = AUTOMOUNT(u);
+        Automount *a = ASSERT_PTR(AUTOMOUNT(u));
         void *p;
         int r;
 
-        assert(a);
         assert(f);
         assert(fds);
 
@@ -873,10 +854,9 @@ static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
 }
 
 static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
-        Automount *a = AUTOMOUNT(u);
+        Automount *a = ASSERT_PTR(AUTOMOUNT(u));
         int r;
 
-        assert(a);
         assert(fds);
 
         if (streq(key, "state")) {
@@ -958,13 +938,12 @@ static bool automount_may_gc(Unit *u) {
 }
 
 static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
+        Automount *a = ASSERT_PTR(AUTOMOUNT(userdata));
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         union autofs_v5_packet_union packet;
-        Automount *a = AUTOMOUNT(userdata);
         Unit *trigger;
         int r;
 
-        assert(a);
         assert(fd == a->pipe_fd);
 
         if (events & (EPOLLHUP|EPOLLERR)) {
@@ -1048,9 +1027,7 @@ static void automount_shutdown(Manager *m) {
 }
 
 static void automount_reset_failed(Unit *u) {
-        Automount *a = AUTOMOUNT(u);
-
-        assert(a);
+        Automount *a = ASSERT_PTR(AUTOMOUNT(u));
 
         if (a->state == AUTOMOUNT_FAILED)
                 automount_set_state(a, AUTOMOUNT_DEAD);
@@ -1068,11 +1045,9 @@ static bool automount_supported(void) {
 }
 
 static int automount_can_start(Unit *u) {
-        Automount *a = AUTOMOUNT(u);
+        Automount *a = ASSERT_PTR(AUTOMOUNT(u));
         int r;
 
-        assert(a);
-
         r = unit_test_start_limit(u);
         if (r < 0) {
                 automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT);
index 6b2d7c3e247f045cd111dfa60738ec943860da84..93cab92b8ce0669e8c4e20301e86a1e49f3617d3 100644 (file)
@@ -119,10 +119,9 @@ static int device_set_sysfs(Device *d, const char *sysfs) {
 }
 
 static void device_init(Unit *u) {
-        Device *d = DEVICE(u);
+        Device *d = ASSERT_PTR(DEVICE(u));
 
-        assert(d);
-        assert(UNIT(d)->load_state == UNIT_STUB);
+        assert(u->load_state == UNIT_STUB);
 
         /* In contrast to all other unit types we timeout jobs waiting
          * for devices by default. This is because they otherwise wait
@@ -137,9 +136,7 @@ static void device_init(Unit *u) {
 }
 
 static void device_done(Unit *u) {
-        Device *d = DEVICE(u);
-
-        assert(d);
+        Device *d = ASSERT_PTR(DEVICE(u));
 
         device_unset_sysfs(d);
         d->deserialized_sysfs = mfree(d->deserialized_sysfs);
@@ -258,9 +255,8 @@ static void device_update_found_by_name(Manager *m, const char *path, DeviceFoun
 }
 
 static int device_coldplug(Unit *u) {
-        Device *d = DEVICE(u);
+        Device *d = ASSERT_PTR(DEVICE(u));
 
-        assert(d);
         assert(d->state == DEVICE_DEAD);
 
         /* First, let's put the deserialized state and found mask into effect, if we have it. */
@@ -336,9 +332,7 @@ static int device_coldplug(Unit *u) {
 }
 
 static void device_catchup(Unit *u) {
-        Device *d = DEVICE(u);
-
-        assert(d);
+        Device *d = ASSERT_PTR(DEVICE(u));
 
         /* Second, let's update the state with the enumerated state */
         device_update_found_one(d, d->enumerated_found, DEVICE_FOUND_MASK);
@@ -405,11 +399,9 @@ static int device_found_from_string_many(const char *name, DeviceFound *ret) {
 }
 
 static int device_serialize(Unit *u, FILE *f, FDSet *fds) {
+        Device *d = ASSERT_PTR(DEVICE(u));
         _cleanup_free_ char *s = NULL;
-        Device *d = DEVICE(u);
 
-        assert(d);
-        assert(u);
         assert(f);
         assert(fds);
 
@@ -428,11 +420,9 @@ static int device_serialize(Unit *u, FILE *f, FDSet *fds) {
 }
 
 static int device_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
-        Device *d = DEVICE(u);
+        Device *d = ASSERT_PTR(DEVICE(u));
         int r;
 
-        assert(d);
-        assert(u);
         assert(key);
         assert(value);
         assert(fds);
@@ -472,10 +462,11 @@ static int device_deserialize_item(Unit *u, const char *key, const char *value,
 }
 
 static void device_dump(Unit *u, FILE *f, const char *prefix) {
-        Device *d = DEVICE(u);
+        Device *d = ASSERT_PTR(DEVICE(u));
         _cleanup_free_ char *s = NULL;
 
-        assert(d);
+        assert(f);
+        assert(prefix);
 
         (void) device_found_to_string_many(d->found, &s);
 
@@ -495,15 +486,15 @@ static void device_dump(Unit *u, FILE *f, const char *prefix) {
 }
 
 static UnitActiveState device_active_state(Unit *u) {
-        assert(u);
+        Device *d = ASSERT_PTR(DEVICE(u));
 
-        return state_translation_table[DEVICE(u)->state];
+        return state_translation_table[d->state];
 }
 
 static const char *device_sub_state_to_string(Unit *u) {
-        assert(u);
+        Device *d = ASSERT_PTR(DEVICE(u));
 
-        return device_state_to_string(DEVICE(u)->state);
+        return device_state_to_string(d->state);
 }
 
 static int device_update_description(Unit *u, sd_device *dev, const char *path) {
@@ -538,12 +529,11 @@ static int device_update_description(Unit *u, sd_device *dev, const char *path)
 }
 
 static int device_add_udev_wants(Unit *u, sd_device *dev) {
+        Device *d = ASSERT_PTR(DEVICE(u));
         _cleanup_strv_free_ char **added = NULL;
         const char *wants, *property;
-        Device *d = DEVICE(u);
         int r;
 
-        assert(d);
         assert(dev);
 
         property = MANAGER_IS_USER(u->manager) ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS";
@@ -646,6 +636,8 @@ static void device_upgrade_mount_deps(Unit *u) {
 
         /* Let's upgrade Requires= to BindsTo= on us. (Used when SYSTEMD_MOUNT_DEVICE_BOUND is set) */
 
+        assert(u);
+
         HASHMAP_FOREACH_KEY(v, other, unit_get_dependencies(u, UNIT_REQUIRED_BY)) {
                 if (other->type != UNIT_MOUNT)
                         continue;
@@ -706,16 +698,18 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool
                 unit_add_to_load_queue(u);
         }
 
-        if (!DEVICE(u)->path) {
-                DEVICE(u)->path = strdup(path);
-                if (!DEVICE(u)->path)
+        Device *d = ASSERT_PTR(DEVICE(u));
+
+        if (!d->path) {
+                d->path = strdup(path);
+                if (!d->path)
                         return log_oom();
         }
 
         /* If this was created via some dependency and has not actually been seen yet ->sysfs will not be
          * initialized. Hence initialize it if necessary. */
         if (sysfs) {
-                r = device_set_sysfs(DEVICE(u), sysfs);
+                r = device_set_sysfs(d, sysfs);
                 if (r < 0)
                         return log_unit_error_errno(u, r, "Failed to set sysfs path %s: %m", sysfs);
 
@@ -730,11 +724,11 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool
          * by systemd before the device appears on its radar. In this case the device unit is partially
          * initialized and includes the deps on the mount unit but at that time the "bind mounts" flag wasn't
          * present. Fix this up now. */
-        if (dev && device_is_bound_by_mounts(DEVICE(u), dev))
+        if (dev && device_is_bound_by_mounts(d, dev))
                 device_upgrade_mount_deps(u);
 
         if (units) {
-                r = set_ensure_put(units, NULL, DEVICE(u));
+                r = set_ensure_put(units, NULL, d);
                 if (r < 0)
                         return log_unit_error_errno(u, r, "Failed to store unit: %m");
         }
@@ -950,10 +944,7 @@ static int device_setup_units(Manager *m, sd_device *dev, Set **ready_units, Set
 }
 
 static Unit *device_following(Unit *u) {
-        Device *d = DEVICE(u);
-        Device *first = NULL;
-
-        assert(d);
+        Device *d = ASSERT_PTR(DEVICE(u)), *first = NULL;
 
         if (startswith(u->id, "sys-"))
                 return NULL;
@@ -973,16 +964,15 @@ static Unit *device_following(Unit *u) {
         return UNIT(first);
 }
 
-static int device_following_set(Unit *u, Set **_set) {
-        Device *d = DEVICE(u);
+static int device_following_set(Unit *u, Set **ret) {
+        Device *d = ASSERT_PTR(DEVICE(u));
         _cleanup_set_free_ Set *set = NULL;
         int r;
 
-        assert(d);
-        assert(_set);
+        assert(ret);
 
         if (LIST_JUST_US(same_sysfs, d)) {
-                *_set = NULL;
+                *ret = NULL;
                 return 0;
         }
 
@@ -1002,7 +992,7 @@ static int device_following_set(Unit *u, Set **_set) {
                         return r;
         }
 
-        *_set = TAKE_PTR(set);
+        *ret = TAKE_PTR(set);
         return 1;
 }
 
index 0db13bfa8807d3c7c960ff393762aa3e4dcfccd2..a1401f3e4903a9586778cffadfacb0f1472c5e87 100644 (file)
@@ -41,6 +41,7 @@
 #include "hexdecoct.h"
 #include "io-util.h"
 #include "iovec-util.h"
+#include "journal-send.h"
 #include "missing_ioprio.h"
 #include "missing_prctl.h"
 #include "missing_securebits.h"
@@ -159,9 +160,11 @@ static int connect_journal_socket(
         const char *j;
         int r;
 
-        j = log_namespace ?
-                strjoina("/run/systemd/journal.", log_namespace, "/stdout") :
-                "/run/systemd/journal/stdout";
+        assert(fd >= 0);
+
+        j = journal_stream_path(log_namespace);
+        if (!j)
+                return -EINVAL;
 
         if (gid_is_valid(gid)) {
                 oldgid = getgid();
index fb3e9b79cbeef1c6d08ed5a69be519b38c1b6443..656547f9030cd248e97305f695edc7e96ca9fb86 100644 (file)
@@ -362,7 +362,7 @@ int exec_spawn(Unit *unit,
                PidRef *ret) {
 
         char serialization_fd_number[DECIMAL_STR_MAX(int) + 1];
-        _cleanup_free_ char *subcgroup_path = NULL, *log_level = NULL, *executor_path = NULL;
+        _cleanup_free_ char *subcgroup_path = NULL, *max_log_levels = NULL, *executor_path = NULL;
         _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
         _cleanup_fdset_free_ FDSet *fdset = NULL;
         _cleanup_fclose_ FILE *f = NULL;
@@ -435,9 +435,9 @@ int exec_spawn(Unit *unit,
         /* If LogLevelMax= is specified, then let's use the specified log level at the beginning of the
          * executor process. To achieve that the specified log level is passed as an argument, rather than
          * the one for the manager process. */
-        r = log_level_to_string_alloc(context->log_level_max >= 0 ? context->log_level_max : log_get_max_level(), &log_level);
+        r = log_max_levels_to_string(context->log_level_max >= 0 ? context->log_level_max : log_get_max_level(), &max_log_levels);
         if (r < 0)
-                return log_unit_error_errno(unit, r, "Failed to convert log level to string: %m");
+                return log_unit_error_errno(unit, r, "Failed to convert max log levels to string: %m");
 
         r = fd_get_path(unit->manager->executor_fd, &executor_path);
         if (r < 0)
@@ -450,7 +450,7 @@ int exec_spawn(Unit *unit,
                         FORMAT_PROC_FD_PATH(unit->manager->executor_fd),
                         STRV_MAKE(executor_path,
                                   "--deserialize", serialization_fd_number,
-                                  "--log-level", log_level,
+                                  "--log-level", max_log_levels,
                                   "--log-target", log_target_to_string(manager_get_executor_log_target(unit->manager))),
                         environ,
                         cg_unified() > 0 ? subcgroup_path : NULL,
index 07ec98252e8465d6958ad5c790455fd09af3aa61..51f64bdc1de1c62fc732c2bcc076540358049b48 100644 (file)
@@ -1508,32 +1508,37 @@ static int become_shutdown(int objective, int retval) {
                 [MANAGER_KEXEC]    = "kexec",
         };
 
-        char log_level[STRLEN("--log-level=") + DECIMAL_STR_MAX(int)],
-             timeout[STRLEN("--timeout=") + DECIMAL_STR_MAX(usec_t) + STRLEN("us")],
+        char timeout[STRLEN("--timeout=") + DECIMAL_STR_MAX(usec_t) + STRLEN("us")],
              exit_code[STRLEN("--exit-code=") + DECIMAL_STR_MAX(uint8_t)];
 
         _cleanup_strv_free_ char **env_block = NULL;
+        _cleanup_free_ char *max_log_levels = NULL;
         usec_t watchdog_timer = 0;
         int r;
 
         assert(objective >= 0 && objective < _MANAGER_OBJECTIVE_MAX);
         assert(table[objective]);
 
-        xsprintf(log_level, "--log-level=%d", log_get_max_level());
         xsprintf(timeout, "--timeout=%" PRI_USEC "us", arg_defaults.timeout_stop_usec);
 
-        const char* command_line[10] = {
+        const char* command_line[11] = {
                 SYSTEMD_SHUTDOWN_BINARY_PATH,
                 table[objective],
-                log_level,
                 timeout,
                 /* Note that the last position is a terminator and must contain NULL. */
         };
-        size_t pos = 4;
+        size_t pos = 3;
 
         assert(command_line[pos-1]);
         assert(!command_line[pos]);
 
+        (void) log_max_levels_to_string(log_get_max_level(), &max_log_levels);
+
+        if (max_log_levels) {
+                command_line[pos++] = "--log-level";
+                command_line[pos++] = max_log_levels;
+        }
+
         switch (log_get_target()) {
 
         case LOG_TARGET_KMSG:
@@ -3282,7 +3287,8 @@ finish:
 #endif
 
         if (r < 0)
-                (void) sd_notifyf(0, "ERRNO=%i", -r);
+                (void) sd_notifyf(/* unset_environment= */ false,
+                                  "ERRNO=%i", -r);
 
         /* Try to invoke the shutdown binary unless we already failed.
          * If we failed above, we want to freeze after finishing cleanup. */
@@ -3295,7 +3301,8 @@ finish:
 
         /* This is primarily useful when running systemd in a VM, as it provides the user running the VM with
          * a mechanism to pick up systemd's exit status in the VM. */
-        (void) sd_notifyf(0, "EXIT_STATUS=%i", retval);
+        (void) sd_notifyf(/* unset_environment= */ false,
+                          "EXIT_STATUS=%i", retval);
 
         watchdog_free_device();
         arg_watchdog_device = mfree(arg_watchdog_device);
index d307c07a624eb392bc9707234e593e1837826933..7eeb7f3a26ba9130f75dbdc54a0702a2286cc7b5 100644 (file)
@@ -264,12 +264,11 @@ static void manager_print_jobs_in_progress(Manager *m) {
                                       strempty(status_text));
         }
 
-        sd_notifyf(false,
-                   "STATUS=%sUser job %s/%s running (%s / %s)...",
-                   job_of_n,
-                   ident,
-                   job_type_to_string(j->type),
-                   time, limit);
+        (void) sd_notifyf(/* unset_environment= */ false,
+                          "STATUS=%sUser job %s/%s running (%s / %s)...",
+                          job_of_n,
+                          ident, job_type_to_string(j->type),
+                          time, limit);
         m->status_ready = false;
 }
 
@@ -483,21 +482,19 @@ static int enable_special_signals(Manager *m) {
         if (MANAGER_IS_TEST_RUN(m))
                 return 0;
 
-        /* Enable that we get SIGINT on control-alt-del. In containers
-         * this will fail with EPERM (older) or EINVAL (newer), so
-         * ignore that. */
+        /* Enable that we get SIGINT on control-alt-del. In containers this will fail with EPERM (older) or
+         * EINVAL (newer), so ignore that. */
         if (reboot(RB_DISABLE_CAD) < 0 && !IN_SET(errno, EPERM, EINVAL))
-                log_warning_errno(errno, "Failed to enable ctrl-alt-del handling: %m");
+                log_warning_errno(errno, "Failed to enable ctrl-alt-del handling, ignoring: %m");
 
         fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
-        if (fd < 0) {
-                /* Support systems without virtual console */
-                if (fd != -ENOENT)
-                        log_warning_errno(errno, "Failed to open /dev/tty0: %m");
-        } else {
+        if (fd < 0)
+                /* Support systems without virtual console (ENOENT) gracefully */
+                log_full_errno(fd == -ENOENT ? LOG_DEBUG : LOG_WARNING, fd, "Failed to open /dev/tty0, ignoring: %m");
+        else {
                 /* Enable that we get SIGWINCH on kbrequest */
                 if (ioctl(fd, KDSIGACCEPT, SIGWINCH) < 0)
-                        log_warning_errno(errno, "Failed to enable kbrequest handling: %m");
+                        log_warning_errno(errno, "Failed to enable kbrequest handling, ignoring: %m");
         }
 
         return 0;
@@ -597,6 +594,17 @@ static int manager_setup_signals(Manager *m) {
         if (r < 0)
                 return r;
 
+        /* Report to supervisor that we now process the above signals. We report this as level "2", to
+         * indicate that we support more than sysvinit's signals (of course, sysvinit never sent this
+         * message, but conceptually it makes sense to consider level "1" to be equivalent to sysvinit's
+         * signal handling). Also, by setting this to "2" people looking for this hopefully won't
+         * misunderstand this as a boolean concept. Signal level 2 shall refer to the signals PID 1
+         * understands at the time of release of systemd v256, i.e. including basic SIGRTMIN+18 handling for
+         * memory pressure and stuff. When more signals are hooked up (or more SIGRTMIN+18 multiplex
+         * operations added, this level should be increased).  */
+        (void) sd_notify(/* unset_environment= */ false,
+                         "X_SYSTEMD_SIGNALS_LEVEL=2");
+
         if (MANAGER_IS_SYSTEM(m))
                 return enable_special_signals(m);
 
@@ -2869,8 +2877,8 @@ static void manager_start_special(Manager *m, const char *name, JobMode mode) {
 
         log_info("Activating special unit %s...", s);
 
-        sd_notifyf(false,
-                   "STATUS=Activating special unit %s...", s);
+        (void) sd_notifyf(/* unset_environment= */ false,
+                          "STATUS=Activating special unit %s...", s);
         m->status_ready = false;
 }
 
@@ -3362,16 +3370,18 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
         const char *msg;
         int audit_fd, r;
 
+        assert(m);
+        assert(u);
+
         if (!MANAGER_IS_SYSTEM(m))
                 return;
 
-        audit_fd = get_audit_fd();
-        if (audit_fd < 0)
+        /* Don't generate audit events if the service was already started and we're just deserializing */
+        if (MANAGER_IS_RELOADING(m))
                 return;
 
-        /* Don't generate audit events if the service was already
-         * started and we're just deserializing */
-        if (MANAGER_IS_RELOADING(m))
+        audit_fd = get_audit_fd();
+        if (audit_fd < 0)
                 return;
 
         r = unit_name_to_prefix_and_instance(u->id, &p);
@@ -3390,21 +3400,22 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
                         log_warning_errno(errno, "Failed to send audit message, ignoring: %m");
         }
 #endif
-
 }
 
 void manager_send_unit_plymouth(Manager *m, Unit *u) {
         _cleanup_free_ char *message = NULL;
         int c, r;
 
-        /* Don't generate plymouth events if the service was already
-         * started and we're just deserializing */
-        if (MANAGER_IS_RELOADING(m))
-                return;
+        assert(m);
+        assert(u);
 
         if (!MANAGER_IS_SYSTEM(m))
                 return;
 
+        /* Don't generate plymouth events if the service was already started and we're just deserializing */
+        if (MANAGER_IS_RELOADING(m))
+                return;
+
         if (detect_container() > 0)
                 return;
 
@@ -3422,6 +3433,27 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) {
                                "Failed to communicate with plymouth: %m");
 }
 
+void manager_send_unit_supervisor(Manager *m, Unit *u, bool active) {
+        assert(m);
+        assert(u);
+
+        /* Notify a "supervisor" process about our progress, i.e. a container manager, hypervisor, or
+         * surrounding service manager. */
+
+        if (MANAGER_IS_RELOADING(m))
+                return;
+
+        if (!UNIT_VTABLE(u)->notify_supervisor)
+                return;
+
+        if (in_initrd()) /* Only send these once we left the initrd */
+                return;
+
+        (void) sd_notifyf(/* unset_environment= */ false,
+                          active ? "X_SYSTEMD_UNIT_ACTIVE=%s" : "X_SYSTEMD_UNIT_INACTIVE=%s",
+                          u->id);
+}
+
 usec_t manager_get_watchdog(Manager *m, WatchdogType t) {
         assert(m);
 
@@ -3731,7 +3763,7 @@ static void manager_notify_finished(Manager *m) {
         log_taint_string(m);
 }
 
-static void user_manager_send_ready(Manager *m) {
+static void manager_send_ready_user_scope(Manager *m) {
         int r;
 
         assert(m);
@@ -3740,7 +3772,7 @@ static void user_manager_send_ready(Manager *m) {
         if (!MANAGER_IS_USER(m) || m->ready_sent)
                 return;
 
-        r = sd_notify(false,
+        r = sd_notify(/* unset_environment= */ false,
                       "READY=1\n"
                       "STATUS=Reached " SPECIAL_BASIC_TARGET ".");
         if (r < 0)
@@ -3750,14 +3782,19 @@ static void user_manager_send_ready(Manager *m) {
         m->status_ready = false;
 }
 
-static void manager_send_ready(Manager *m) {
+static void manager_send_ready_system_scope(Manager *m) {
         int r;
 
+        assert(m);
+
+        if (!MANAGER_IS_SYSTEM(m))
+                return;
+
+        /* Skip the notification if nothing changed. */
         if (m->ready_sent && m->status_ready)
-                /* Skip the notification if nothing changed. */
                 return;
 
-        r = sd_notify(false,
+        r = sd_notify(/* unset_environment= */ false,
                       "READY=1\n"
                       "STATUS=Ready.");
         if (r < 0)
@@ -3781,7 +3818,7 @@ static void manager_check_basic_target(Manager *m) {
                 return;
 
         /* For user managers, send out READY=1 as soon as we reach basic.target */
-        user_manager_send_ready(m);
+        manager_send_ready_user_scope(m);
 
         /* Log the taint string as soon as we reach basic.target */
         log_taint_string(m);
@@ -3812,7 +3849,7 @@ void manager_check_finished(Manager *m) {
         if (hashmap_buckets(m->jobs) > hashmap_size(m->units) / 10)
                 m->jobs = hashmap_free(m->jobs);
 
-        manager_send_ready(m);
+        manager_send_ready_system_scope(m);
 
         /* Notify Type=idle units that we are done now */
         manager_close_idle_pipe(m);
@@ -3842,7 +3879,7 @@ void manager_send_reloading(Manager *m) {
         assert(m);
 
         /* Let whoever invoked us know that we are now reloading */
-        (void) sd_notifyf(/* unset= */ false,
+        (void) sd_notifyf(/* unset_environment= */ false,
                           "RELOADING=1\n"
                           "MONOTONIC_USEC=" USEC_FMT "\n", now(CLOCK_MONOTONIC));
 
index 9f1a21b22dbe82592f2ff77ceb77875f8fcc33e9..4d82c4a6a0daa7f91418057b61eca7ec0c118cd5 100644 (file)
@@ -575,6 +575,7 @@ void manager_reset_failed(Manager *m);
 
 void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success);
 void manager_send_unit_plymouth(Manager *m, Unit *u);
+void manager_send_unit_supervisor(Manager *m, Unit *u, bool active);
 
 bool manager_unit_inactive_or_pending(Manager *m, const char *name);
 
index 7dbf5f48f9722bcdf13c107a3ec784ec455387a6..f574e28ec474cc025ffdb2b8b6f097abc937b8ba 100644 (file)
@@ -172,10 +172,8 @@ static bool mount_propagate_stop(Mount *m) {
 }
 
 static void mount_init(Unit *u) {
-        Mount *m = MOUNT(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
 
-        assert(m);
-        assert(u);
         assert(u->load_state == UNIT_STUB);
 
         m->timeout_usec = u->manager->defaults.timeout_start_usec;
@@ -217,9 +215,7 @@ static void mount_parameters_done(MountParameters *p) {
 }
 
 static void mount_done(Unit *u) {
-        Mount *m = MOUNT(u);
-
-        assert(m);
+        Mount *m = ASSERT_PTR(MOUNT(u));
 
         m->where = mfree(m->where);
 
@@ -245,6 +241,8 @@ static int update_parameters_proc_self_mountinfo(
         MountParameters *p;
         int r, q, w;
 
+        assert(m);
+
         p = &m->parameters_proc_self_mountinfo;
 
         r = free_and_strdup(&p->what, what);
@@ -408,9 +406,8 @@ static int mount_add_device_dependencies(Mount *m) {
 }
 
 static bool mount_is_extrinsic(Unit *u) {
+        Mount *m = ASSERT_PTR(MOUNT(u));
         MountParameters *p;
-        Mount *m = MOUNT(u);
-        assert(m);
 
         /* Returns true for all units that are "magic" and should be excluded from the usual
          * start-up and shutdown dependencies. We call them "extrinsic" here, as they are generally
@@ -629,11 +626,9 @@ static int mount_add_non_exec_dependencies(Mount *m) {
 }
 
 static int mount_add_extras(Mount *m) {
-        Unit *u = UNIT(m);
+        Unit *u = UNIT(ASSERT_PTR(m));
         int r;
 
-        assert(m);
-
         /* Note: this call might be called after we already have been loaded once (and even when it has already been
          * activated), in case data from /proc/self/mountinfo has changed. This means all code here needs to be ready
          * to run with an already set up unit. */
@@ -678,7 +673,7 @@ static int mount_add_extras(Mount *m) {
 }
 
 static void mount_load_root_mount(Unit *u) {
-        assert(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
 
         if (!unit_has_name(u, SPECIAL_ROOT_MOUNT))
                 return;
@@ -687,37 +682,35 @@ static void mount_load_root_mount(Unit *u) {
         u->default_dependencies = false;
 
         /* The stdio/kmsg bridge socket is on /, in order to avoid a dep loop, don't use kmsg logging for -.mount */
-        MOUNT(u)->exec_context.std_output = EXEC_OUTPUT_NULL;
-        MOUNT(u)->exec_context.std_input = EXEC_INPUT_NULL;
+        m->exec_context.std_output = EXEC_OUTPUT_NULL;
+        m->exec_context.std_input = EXEC_INPUT_NULL;
 
         if (!u->description)
                 u->description = strdup("Root Mount");
 }
 
 static int mount_load(Unit *u) {
-        Mount *m = MOUNT(u);
-        int r, q = 0;
+        Mount *m = ASSERT_PTR(MOUNT(u));
+        int r;
 
-        assert(m);
-        assert(u);
         assert(u->load_state == UNIT_STUB);
 
         mount_load_root_mount(u);
 
-        bool fragment_optional = m->from_proc_self_mountinfo || u->perpetual;
-        r = unit_load_fragment_and_dropin(u, !fragment_optional);
+        bool from_kernel = m->from_proc_self_mountinfo || u->perpetual;
+
+        r = unit_load_fragment_and_dropin(u, /* fragment_required = */ !from_kernel);
 
         /* Add in some extras. Note we do this in all cases (even if we failed to load the unit) when announced by the
          * kernel, because we need some things to be set up no matter what when the kernel establishes a mount and thus
          * we need to update the state in our unit to track it. After all, consider that we don't allow changing the
          * 'slice' field for a unit once it is active. */
-        if (u->load_state == UNIT_LOADED || m->from_proc_self_mountinfo || u->perpetual)
-                q = mount_add_extras(m);
+        if (u->load_state == UNIT_LOADED || from_kernel)
+                RET_GATHER(r, mount_add_extras(m));
 
         if (r < 0)
                 return r;
-        if (q < 0)
-                return q;
+
         if (u->load_state != UNIT_LOADED)
                 return 0;
 
@@ -726,6 +719,7 @@ static int mount_load(Unit *u) {
 
 static void mount_set_state(Mount *m, MountState state) {
         MountState old_state;
+
         assert(m);
 
         if (m->state != state)
@@ -748,10 +742,9 @@ static void mount_set_state(Mount *m, MountState state) {
 }
 
 static int mount_coldplug(Unit *u) {
-        Mount *m = MOUNT(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
         int r;
 
-        assert(m);
         assert(m->state == MOUNT_DEAD);
 
         if (m->deserialized_state == m->state)
@@ -780,9 +773,7 @@ static int mount_coldplug(Unit *u) {
 }
 
 static void mount_catchup(Unit *u) {
-        Mount *m = MOUNT(ASSERT_PTR(u));
-
-        assert(m);
+        Mount *m = ASSERT_PTR(MOUNT(u));
 
         /* Adjust the deserialized state. See comments in mount_process_proc_self_mountinfo(). */
         if (m->from_proc_self_mountinfo)
@@ -817,10 +808,9 @@ static void mount_catchup(Unit *u) {
 }
 
 static void mount_dump(Unit *u, FILE *f, const char *prefix) {
-        Mount *m = MOUNT(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
         MountParameters *p;
 
-        assert(m);
         assert(f);
 
         p = get_mount_parameters(m);
@@ -870,7 +860,6 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
 }
 
 static int mount_spawn(Mount *m, ExecCommand *c, PidRef *ret_pid) {
-
         _cleanup_(exec_params_shallow_clear) ExecParameters exec_params = EXEC_PARAMETERS_INIT(
                         EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN);
         _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
@@ -1115,9 +1104,9 @@ static int mount_set_mount_command(Mount *m, ExecCommand *c, const MountParamete
 }
 
 static void mount_enter_mounting(Mount *m) {
-        int r;
         MountParameters *p;
         bool source_is_dir = true;
+        int r;
 
         assert(m);
 
@@ -1226,8 +1215,8 @@ static void mount_set_reload_result(Mount *m, MountResult result) {
 }
 
 static void mount_enter_remounting(Mount *m) {
-        int r;
         MountParameters *p;
+        int r;
 
         assert(m);
 
@@ -1295,11 +1284,9 @@ static void mount_cycle_clear(Mount *m) {
 }
 
 static int mount_start(Unit *u) {
-        Mount *m = MOUNT(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
         int r;
 
-        assert(m);
-
         /* We cannot fulfill this request right now, try again later
          * please! */
         if (IN_SET(m->state,
@@ -1326,9 +1313,7 @@ static int mount_start(Unit *u) {
 }
 
 static int mount_stop(Unit *u) {
-        Mount *m = MOUNT(u);
-
-        assert(m);
+        Mount *m = ASSERT_PTR(MOUNT(u));
 
         /* When we directly call umount() for a path, then the state of the corresponding mount unit may be
          * outdated. Let's re-read mountinfo now and update the state. */
@@ -1380,9 +1365,8 @@ static int mount_stop(Unit *u) {
 }
 
 static int mount_reload(Unit *u) {
-        Mount *m = MOUNT(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
 
-        assert(m);
         assert(m->state == MOUNT_MOUNTED);
 
         mount_enter_remounting(m);
@@ -1391,9 +1375,8 @@ static int mount_reload(Unit *u) {
 }
 
 static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
-        Mount *m = MOUNT(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
 
-        assert(m);
         assert(f);
         assert(fds);
 
@@ -1410,11 +1393,9 @@ static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
 }
 
 static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
-        Mount *m = MOUNT(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
         int r;
 
-        assert(m);
-        assert(u);
         assert(key);
         assert(value);
         assert(fds);
@@ -1474,21 +1455,19 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F
 }
 
 static UnitActiveState mount_active_state(Unit *u) {
-        assert(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
 
-        return state_translation_table[MOUNT(u)->state];
+        return state_translation_table[m->state];
 }
 
 static const char *mount_sub_state_to_string(Unit *u) {
-        assert(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
 
-        return mount_state_to_string(MOUNT(u)->state);
+        return mount_state_to_string(m->state);
 }
 
 static bool mount_may_gc(Unit *u) {
-        Mount *m = MOUNT(u);
-
-        assert(m);
+        Mount *m = ASSERT_PTR(MOUNT(u));
 
         if (m->from_proc_self_mountinfo)
                 return false;
@@ -1497,10 +1476,9 @@ static bool mount_may_gc(Unit *u) {
 }
 
 static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
-        Mount *m = MOUNT(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
         MountResult f;
 
-        assert(m);
         assert(pid >= 0);
 
         if (pid != m->control_pid.pid)
@@ -1627,9 +1605,8 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 }
 
 static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
-        Mount *m = MOUNT(userdata);
+        Mount *m = ASSERT_PTR(MOUNT(userdata));
 
-        assert(m);
         assert(m->timer_event_source == source);
 
         switch (m->state) {
@@ -1712,6 +1689,7 @@ static int mount_setup_new_unit(
                 Unit **ret) {
 
         _cleanup_(unit_freep) Unit *u = NULL;
+        Mount *mnt;
         int r;
 
         assert(m);
@@ -1723,24 +1701,26 @@ static int mount_setup_new_unit(
         if (r < 0)
                 return r;
 
+        mnt = ASSERT_PTR(MOUNT(u));
+
         r = free_and_strdup(&u->source_path, "/proc/self/mountinfo");
         if (r < 0)
                 return r;
 
-        r = free_and_strdup(&MOUNT(u)->where, where);
+        r = free_and_strdup(&mnt->where, where);
         if (r < 0)
                 return r;
 
-        r = update_parameters_proc_self_mountinfo(MOUNT(u), what, options, fstype);
+        r = update_parameters_proc_self_mountinfo(mnt, what, options, fstype);
         if (r < 0)
                 return r;
 
         /* This unit was generated because /proc/self/mountinfo reported it. Remember this, so that by the
          * time we load the unit file for it (and thus add in extra deps right after) we know what source to
          * attributes the deps to. */
-        MOUNT(u)->from_proc_self_mountinfo = true;
+        mnt->from_proc_self_mountinfo = true;
 
-        r = mount_add_non_exec_dependencies(MOUNT(u));
+        r = mount_add_non_exec_dependencies(mnt);
         if (r < 0)
                 return r;
 
@@ -1761,14 +1741,16 @@ static int mount_setup_existing_unit(
                 const char *fstype,
                 MountProcFlags *ret_flags) {
 
+        Mount *m = ASSERT_PTR(MOUNT(u));
         int r;
 
         assert(u);
+        assert(where);
         assert(ret_flags);
 
-        if (!MOUNT(u)->where) {
-                MOUNT(u)->where = strdup(where);
-                if (!MOUNT(u)->where)
+        if (!m->where) {
+                m->where = strdup(where);
+                if (!m->where)
                         return -ENOMEM;
         }
 
@@ -1776,10 +1758,9 @@ static int mount_setup_existing_unit(
          * for the current unit. Note that the flags field is reset on each iteration of reading
          * /proc/self/mountinfo, hence we know for sure anything already set here is from the current
          * iteration and thus worthy of taking into account. */
-        MountProcFlags flags =
-                MOUNT(u)->proc_flags | MOUNT_PROC_IS_MOUNTED;
+        MountProcFlags flags = m->proc_flags | MOUNT_PROC_IS_MOUNTED;
 
-        r = update_parameters_proc_self_mountinfo(MOUNT(u), what, options, fstype);
+        r = update_parameters_proc_self_mountinfo(m, what, options, fstype);
         if (r < 0)
                 return r;
         if (r > 0)
@@ -1792,10 +1773,10 @@ static int mount_setup_existing_unit(
          * from the serialized state), and need to catch up. Since we know that the MOUNT_MOUNTING state is
          * reached when we wait for the mount to appear we hence can assume that if we are in it, we are
          * actually seeing it established for the first time. */
-        if (!MOUNT(u)->from_proc_self_mountinfo || MOUNT(u)->state == MOUNT_MOUNTING)
+        if (!m->from_proc_self_mountinfo || m->state == MOUNT_MOUNTING)
                 flags |= MOUNT_PROC_JUST_MOUNTED;
 
-        MOUNT(u)->from_proc_self_mountinfo = true;
+        m->from_proc_self_mountinfo = true;
 
         if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) {
                 /* The unit was previously not found or otherwise not loaded. Now that the unit shows up in
@@ -1809,7 +1790,7 @@ static int mount_setup_existing_unit(
         if (FLAGS_SET(flags, MOUNT_PROC_JUST_CHANGED)) {
                 /* If things changed, then make sure that all deps are regenerated. Let's
                  * first remove all automatic deps, and then add in the new ones. */
-                r = mount_add_non_exec_dependencies(MOUNT(u));
+                r = mount_add_non_exec_dependencies(m);
                 if (r < 0)
                         return r;
         }
@@ -1925,13 +1906,10 @@ static void mount_shutdown(Manager *m) {
 }
 
 static int mount_get_timeout(Unit *u, usec_t *timeout) {
-        Mount *m = MOUNT(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
         usec_t t;
         int r;
 
-        assert(m);
-        assert(u);
-
         if (!m->timer_event_source)
                 return 0;
 
@@ -2301,19 +2279,15 @@ fail:
 }
 
 static int mount_can_clean(Unit *u, ExecCleanMask *ret) {
-        Mount *m = MOUNT(u);
-
-        assert(m);
+        Mount *m = ASSERT_PTR(MOUNT(u));
 
         return exec_context_get_clean_mask(&m->exec_context, ret);
 }
 
 static int mount_can_start(Unit *u) {
-        Mount *m = MOUNT(u);
+        Mount *m = ASSERT_PTR(MOUNT(u));
         int r;
 
-        assert(m);
-
         r = unit_test_start_limit(u);
         if (r < 0) {
                 mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
index 00da301fd2225caf0dc752895c64579150acfc41..fdb6ca4cc9db22b08bac5d2b738da97cd066d2ec 100644 (file)
@@ -249,6 +249,8 @@ static bool path_spec_check_good(PathSpec *s, bool initial, bool from_trigger_no
 static void path_spec_mkdir(PathSpec *s, mode_t mode) {
         int r;
 
+        assert(s);
+
         if (IN_SET(s->type, PATH_EXISTS, PATH_EXISTS_GLOB))
                 return;
 
@@ -260,6 +262,10 @@ static void path_spec_mkdir(PathSpec *s, mode_t mode) {
 static void path_spec_dump(PathSpec *s, FILE *f, const char *prefix) {
         const char *type;
 
+        assert(s);
+        assert(f);
+        assert(prefix);
+
         assert_se(type = path_type_to_string(s->type));
         fprintf(f, "%s%s: %s\n", prefix, type, s->path);
 }
@@ -272,9 +278,8 @@ void path_spec_done(PathSpec *s) {
 }
 
 static void path_init(Unit *u) {
-        Path *p = PATH(u);
+        Path *p = ASSERT_PTR(PATH(u));
 
-        assert(u);
         assert(u->load_state == UNIT_STUB);
 
         p->directory_mode = 0755;
@@ -295,9 +300,7 @@ void path_free_specs(Path *p) {
 }
 
 static void path_done(Unit *u) {
-        Path *p = PATH(u);
-
-        assert(p);
+        Path *p = ASSERT_PTR(PATH(u));
 
         p->trigger_notify_event_source = sd_event_source_disable_unref(p->trigger_notify_event_source);
         path_free_specs(p);
@@ -389,10 +392,9 @@ static int path_add_extras(Path *p) {
 }
 
 static int path_load(Unit *u) {
-        Path *p = PATH(u);
+        Path *p = ASSERT_PTR(PATH(u));
         int r;
 
-        assert(u);
         assert(u->load_state == UNIT_STUB);
 
         r = unit_load_fragment_and_dropin(u, true);
@@ -410,11 +412,11 @@ static int path_load(Unit *u) {
 }
 
 static void path_dump(Unit *u, FILE *f, const char *prefix) {
-        Path *p = PATH(u);
+        Path *p = ASSERT_PTR(PATH(u));
         Unit *trigger;
 
-        assert(p);
         assert(f);
+        assert(prefix);
 
         trigger = UNIT_TRIGGER(u);
 
@@ -461,6 +463,7 @@ static int path_watch(Path *p) {
 
 static void path_set_state(Path *p, PathState state) {
         PathState old_state;
+
         assert(p);
 
         if (p->state != state)
@@ -481,9 +484,8 @@ static void path_set_state(Path *p, PathState state) {
 static void path_enter_waiting(Path *p, bool initial, bool from_trigger_notify);
 
 static int path_coldplug(Unit *u) {
-        Path *p = PATH(u);
+        Path *p = ASSERT_PTR(PATH(u));
 
-        assert(p);
         assert(p->state == PATH_DEAD);
 
         if (p->deserialized_state != p->state) {
@@ -625,10 +627,9 @@ static void path_mkdir(Path *p) {
 }
 
 static int path_start(Unit *u) {
-        Path *p = PATH(u);
+        Path *p = ASSERT_PTR(PATH(u));
         int r;
 
-        assert(p);
         assert(IN_SET(p->state, PATH_DEAD, PATH_FAILED));
 
         r = unit_test_trigger_loaded(u);
@@ -648,9 +649,8 @@ static int path_start(Unit *u) {
 }
 
 static int path_stop(Unit *u) {
-        Path *p = PATH(u);
+        Path *p = ASSERT_PTR(PATH(u));
 
-        assert(p);
         assert(IN_SET(p->state, PATH_WAITING, PATH_RUNNING));
 
         path_enter_dead(p, PATH_SUCCESS);
@@ -658,9 +658,8 @@ static int path_stop(Unit *u) {
 }
 
 static int path_serialize(Unit *u, FILE *f, FDSet *fds) {
-        Path *p = PATH(u);
+        Path *p = ASSERT_PTR(PATH(u));
 
-        assert(u);
         assert(f);
         assert(fds);
 
@@ -688,9 +687,8 @@ static int path_serialize(Unit *u, FILE *f, FDSet *fds) {
 }
 
 static int path_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
-        Path *p = PATH(u);
+        Path *p = ASSERT_PTR(PATH(u));
 
-        assert(u);
         assert(key);
         assert(value);
         assert(fds);
@@ -755,28 +753,24 @@ static int path_deserialize_item(Unit *u, const char *key, const char *value, FD
 }
 
 static UnitActiveState path_active_state(Unit *u) {
-        assert(u);
+        Path *p = ASSERT_PTR(PATH(u));
 
-        return state_translation_table[PATH(u)->state];
+        return state_translation_table[p->state];
 }
 
 static const char *path_sub_state_to_string(Unit *u) {
-        assert(u);
+        Path *p = ASSERT_PTR(PATH(u));
 
-        return path_state_to_string(PATH(u)->state);
+        return path_state_to_string(p->state);
 }
 
 static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
-        PathSpec *s = userdata, *found = NULL;
-        Path *p;
+        PathSpec *s = ASSERT_PTR(userdata), *found = NULL;
+        Path *p = ASSERT_PTR(PATH(s->unit));
         int changed;
 
-        assert(s);
-        assert(s->unit);
         assert(fd >= 0);
 
-        p = PATH(s->unit);
-
         if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING))
                 return 0;
 
@@ -827,10 +821,9 @@ static int path_trigger_notify_on_defer(sd_event_source *s, void *userdata) {
 }
 
 static void path_trigger_notify_impl(Unit *u, Unit *other, bool on_defer) {
-        Path *p = PATH(u);
+        Path *p = ASSERT_PTR(PATH(u));
         int r;
 
-        assert(u);
         assert(other);
 
         /* Invoked whenever the unit we trigger changes state or gains or loses a job */
@@ -897,9 +890,7 @@ static void path_trigger_notify(Unit *u, Unit *other) {
 }
 
 static void path_reset_failed(Unit *u) {
-        Path *p = PATH(u);
-
-        assert(p);
+        Path *p = ASSERT_PTR(PATH(u));
 
         if (p->state == PATH_FAILED)
                 path_set_state(p, PATH_DEAD);
@@ -908,11 +899,9 @@ static void path_reset_failed(Unit *u) {
 }
 
 static int path_can_start(Unit *u) {
-        Path *p = PATH(u);
+        Path *p = ASSERT_PTR(PATH(u));
         int r;
 
-        assert(p);
-
         r = unit_test_start_limit(u);
         if (r < 0) {
                 path_enter_dead(p, PATH_FAILURE_START_LIMIT_HIT);
@@ -961,13 +950,11 @@ static int activation_details_path_deserialize(const char *key, const char *valu
 }
 
 static int activation_details_path_append_env(ActivationDetails *details, char ***strv) {
-        ActivationDetailsPath *p = ACTIVATION_DETAILS_PATH(details);
+        ActivationDetailsPath *p = ASSERT_PTR(ACTIVATION_DETAILS_PATH(details));
         char *s;
         int r;
 
-        assert(details);
         assert(strv);
-        assert(p);
 
         if (isempty(p->trigger_path_filename))
                 return 0;
@@ -984,12 +971,10 @@ static int activation_details_path_append_env(ActivationDetails *details, char *
 }
 
 static int activation_details_path_append_pair(ActivationDetails *details, char ***strv) {
-        ActivationDetailsPath *p = ACTIVATION_DETAILS_PATH(details);
+        ActivationDetailsPath *p = ASSERT_PTR(ACTIVATION_DETAILS_PATH(details));
         int r;
 
-        assert(details);
         assert(strv);
-        assert(p);
 
         if (isempty(p->trigger_path_filename))
                 return 0;
index 419370590956f7cd7367f8c3b4f5109d10d3bea3..edce5901547a15b47f03849be5c64643ea34b116 100644 (file)
@@ -35,9 +35,8 @@ static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
 
 static void scope_init(Unit *u) {
-        Scope *s = SCOPE(u);
+        Scope *s = ASSERT_PTR(SCOPE(u));
 
-        assert(u);
         assert(u->load_state == UNIT_STUB);
 
         s->runtime_max_usec = USEC_INFINITY;
@@ -48,9 +47,7 @@ static void scope_init(Unit *u) {
 }
 
 static void scope_done(Unit *u) {
-        Scope *s = SCOPE(u);
-
-        assert(u);
+        Scope *s = ASSERT_PTR(SCOPE(u));
 
         s->controller = mfree(s->controller);
         s->controller_track = sd_bus_track_unref(s->controller_track);
@@ -84,6 +81,7 @@ static int scope_arm_timer(Scope *s, bool relative, usec_t usec) {
 
 static void scope_set_state(Scope *s, ScopeState state) {
         ScopeState old_state;
+
         assert(s);
 
         if (s->state != state)
@@ -181,10 +179,9 @@ static int scope_add_extras(Scope *s) {
 }
 
 static int scope_load(Unit *u) {
-        Scope *s = SCOPE(u);
+        Scope *s = ASSERT_PTR(SCOPE(u));
         int r;
 
-        assert(s);
         assert(u->load_state == UNIT_STUB);
 
         if (!u->transient && !MANAGER_IS_RELOADING(u->manager))
@@ -227,10 +224,9 @@ static usec_t scope_coldplug_timeout(Scope *s) {
 }
 
 static int scope_coldplug(Unit *u) {
-        Scope *s = SCOPE(u);
+        Scope *s = ASSERT_PTR(SCOPE(u));
         int r;
 
-        assert(s);
         assert(s->state == SCOPE_DEAD);
 
         if (s->deserialized_state == s->state)
@@ -260,10 +256,10 @@ static int scope_coldplug(Unit *u) {
 }
 
 static void scope_dump(Unit *u, FILE *f, const char *prefix) {
-        Scope *s = SCOPE(u);
+        Scope *s = ASSERT_PTR(SCOPE(u));
 
-        assert(s);
         assert(f);
+        assert(prefix);
 
         fprintf(f,
                 "%sScope State: %s\n"
@@ -277,7 +273,7 @@ static void scope_dump(Unit *u, FILE *f, const char *prefix) {
                 prefix, FORMAT_TIMESPAN(s->runtime_rand_extra_usec, USEC_PER_SEC),
                 prefix, oom_policy_to_string(s->oom_policy));
 
-        cgroup_context_dump(UNIT(s), f, prefix);
+        cgroup_context_dump(u, f, prefix);
         kill_context_dump(&s->kill_context, f, prefix);
 }
 
@@ -346,11 +342,10 @@ fail:
 }
 
 static int scope_enter_start_chown(Scope *s) {
+        Unit *u = UNIT(ASSERT_PTR(s));
         _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
-        Unit *u = UNIT(s);
         int r;
 
-        assert(s);
         assert(s->user);
 
         if (!s->cgroup_runtime)
@@ -410,11 +405,9 @@ fail:
 }
 
 static int scope_enter_running(Scope *s) {
-        Unit *u = UNIT(s);
+        Unit *u = UNIT(ASSERT_PTR(s));
         int r;
 
-        assert(s);
-
         (void) bus_scope_track_controller(s);
 
         r = unit_acquire_invocation_id(u);
@@ -457,9 +450,7 @@ fail:
 }
 
 static int scope_start(Unit *u) {
-        Scope *s = SCOPE(u);
-
-        assert(s);
+        Scope *s = ASSERT_PTR(SCOPE(u));
 
         if (unit_has_name(u, SPECIAL_INIT_SCOPE))
                 return -EPERM;
@@ -488,9 +479,7 @@ static int scope_start(Unit *u) {
 }
 
 static int scope_stop(Unit *u) {
-        Scope *s = SCOPE(u);
-
-        assert(s);
+        Scope *s = ASSERT_PTR(SCOPE(u));
 
         if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
                 return 0;
@@ -502,9 +491,7 @@ static int scope_stop(Unit *u) {
 }
 
 static void scope_reset_failed(Unit *u) {
-        Scope *s = SCOPE(u);
-
-        assert(s);
+        Scope *s = ASSERT_PTR(SCOPE(u));
 
         if (s->state == SCOPE_FAILED)
                 scope_set_state(s, SCOPE_DEAD);
@@ -513,7 +500,7 @@ static void scope_reset_failed(Unit *u) {
 }
 
 static int scope_get_timeout(Unit *u, usec_t *timeout) {
-        Scope *s = SCOPE(u);
+        Scope *s = ASSERT_PTR(SCOPE(u));
         usec_t t;
         int r;
 
@@ -531,10 +518,9 @@ static int scope_get_timeout(Unit *u, usec_t *timeout) {
 }
 
 static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
-        Scope *s = SCOPE(u);
+        Scope *s = ASSERT_PTR(SCOPE(u));
         PidRef *pid;
 
-        assert(s);
         assert(f);
         assert(fds);
 
@@ -551,10 +537,9 @@ static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
 }
 
 static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
-        Scope *s = SCOPE(u);
+        Scope *s = ASSERT_PTR(SCOPE(u));
         int r;
 
-        assert(u);
         assert(key);
         assert(value);
         assert(fds);
@@ -597,8 +582,7 @@ static int scope_deserialize_item(Unit *u, const char *key, const char *value, F
 }
 
 static void scope_notify_cgroup_empty_event(Unit *u) {
-        Scope *s = SCOPE(u);
-        assert(u);
+        Scope *s = ASSERT_PTR(SCOPE(u));
 
         log_unit_debug(u, "cgroup is empty");
 
@@ -607,7 +591,7 @@ static void scope_notify_cgroup_empty_event(Unit *u) {
 }
 
 static void scope_notify_cgroup_oom_event(Unit *u, bool managed_oom) {
-        Scope *s = SCOPE(u);
+        Scope *s = ASSERT_PTR(SCOPE(u));
 
         if (managed_oom)
                 log_unit_debug(u, "Process(es) of control group were killed by systemd-oomd.");
@@ -639,9 +623,7 @@ static void scope_notify_cgroup_oom_event(Unit *u, bool managed_oom) {
 }
 
 static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
-        Scope *s = SCOPE(u);
-
-        assert(s);
+        Scope *s = ASSERT_PTR(SCOPE(u));
 
         if (s->state == SCOPE_START_CHOWN) {
                 if (!is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
@@ -659,9 +641,8 @@ static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 }
 
 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
-        Scope *s = SCOPE(userdata);
+        Scope *s = ASSERT_PTR(SCOPE(userdata));
 
-        assert(s);
         assert(s->timer_event_source == source);
 
         switch (s->state) {
@@ -723,15 +704,15 @@ int scope_abandon(Scope *s) {
 }
 
 static UnitActiveState scope_active_state(Unit *u) {
-        assert(u);
+        Scope *s = ASSERT_PTR(SCOPE(u));
 
-        return state_translation_table[SCOPE(u)->state];
+        return state_translation_table[s->state];
 }
 
 static const char *scope_sub_state_to_string(Unit *u) {
-        assert(u);
+        Scope *s = ASSERT_PTR(SCOPE(u));
 
-        return scope_state_to_string(SCOPE(u)->state);
+        return scope_state_to_string(s->state);
 }
 
 static void scope_enumerate_perpetual(Manager *m) {
index a9047be1cafdb2a698847f4393e579a75b55f1bf..38fb07d5948d6b7705d41763632bb446c4d28c88 100644 (file)
@@ -180,6 +180,8 @@ static void service_unwatch_main_pid(Service *s) {
 }
 
 static void service_unwatch_pid_file(Service *s) {
+        assert(s);
+
         if (!s->pid_file_pathspec)
                 return;
 
@@ -450,9 +452,7 @@ static void service_release_stdio_fd(Service *s) {
 }
 
 static void service_done(Unit *u) {
-        Service *s = SERVICE(u);
-
-        assert(s);
+        Service *s = ASSERT_PTR(SERVICE(u));
 
         open_file_free_many(&s->open_files);
 
@@ -865,7 +865,7 @@ static int service_add_extras(Service *s) {
 }
 
 static int service_load(Unit *u) {
-        Service *s = SERVICE(u);
+        Service *s = ASSERT_PTR(SERVICE(u));
         int r;
 
         r = unit_load_fragment_and_dropin(u, true);
@@ -920,11 +920,9 @@ static void service_dump_fdstore(Service *s, FILE *f, const char *prefix) {
 }
 
 static void service_dump(Unit *u, FILE *f, const char *prefix) {
-        Service *s = SERVICE(u);
+        Service *s = ASSERT_PTR(SERVICE(u));
         const char *prefix2;
 
-        assert(s);
-
         prefix = strempty(prefix);
         prefix2 = strjoina(prefix, "\t");
 
@@ -2234,6 +2232,7 @@ static void service_enter_stop(Service *s, ServiceResult f) {
 
 static bool service_good(Service *s) {
         int main_pid_ok;
+
         assert(s);
 
         if (s->type == SERVICE_DBUS && !s->bus_name_good)
@@ -2290,6 +2289,7 @@ static void service_enter_running(Service *s, ServiceResult f) {
 
 static void service_enter_start_post(Service *s) {
         int r;
+
         assert(s);
 
         service_unwatch_control_pid(s);
@@ -2784,9 +2784,7 @@ static int service_start(Unit *u) {
 }
 
 static int service_stop(Unit *u) {
-        Service *s = SERVICE(u);
-
-        assert(s);
+        Service *s = ASSERT_PTR(SERVICE(u));
 
         /* Don't create restart jobs from manual stops. */
         s->forbid_restart = true;
@@ -2843,9 +2841,7 @@ static int service_stop(Unit *u) {
 }
 
 static int service_reload(Unit *u) {
-        Service *s = SERVICE(u);
-
-        assert(s);
+        Service *s = ASSERT_PTR(SERVICE(u));
 
         assert(IN_SET(s->state, SERVICE_RUNNING, SERVICE_EXITED));
 
@@ -2854,9 +2850,7 @@ static int service_reload(Unit *u) {
 }
 
 static bool service_can_reload(Unit *u) {
-        Service *s = SERVICE(u);
-
-        assert(s);
+        Service *s = ASSERT_PTR(SERVICE(u));
 
         return s->exec_command[SERVICE_EXEC_RELOAD] ||
                 s->type == SERVICE_NOTIFY_RELOAD;
@@ -2880,14 +2874,13 @@ static unsigned service_exec_command_index(Unit *u, ServiceExecCommand id, const
 }
 
 static int service_serialize_exec_command(Unit *u, FILE *f, const ExecCommand *command) {
+        Service *s = ASSERT_PTR(SERVICE(u));
         _cleanup_free_ char *args = NULL, *p = NULL;
-        Service *s = SERVICE(u);
         const char *type, *key;
         ServiceExecCommand id;
         size_t length = 0;
         unsigned idx;
 
-        assert(s);
         assert(f);
 
         if (!command)
@@ -2949,10 +2942,9 @@ static int service_serialize_exec_command(Unit *u, FILE *f, const ExecCommand *c
 }
 
 static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
-        Service *s = SERVICE(u);
+        Service *s = ASSERT_PTR(SERVICE(u));
         int r;
 
-        assert(u);
         assert(f);
         assert(fds);
 
@@ -3055,14 +3047,14 @@ int service_deserialize_exec_command(
                 const char *key,
                 const char *value) {
 
-        Service *s = SERVICE(u);
-        int r;
-        unsigned idx = 0, i;
-        bool control, found = false, last = false;
-        ServiceExecCommand id = _SERVICE_EXEC_COMMAND_INVALID;
+        Service *s = ASSERT_PTR(SERVICE(u));
         ExecCommand *command = NULL;
+        ServiceExecCommand id = _SERVICE_EXEC_COMMAND_INVALID;
         _cleanup_free_ char *path = NULL;
         _cleanup_strv_free_ char **argv = NULL;
+        unsigned idx = 0, i;
+        bool control, found = false, last = false;
+        int r;
 
         enum ExecCommandState {
                 STATE_EXEC_COMMAND_TYPE,
@@ -3073,7 +3065,6 @@ int service_deserialize_exec_command(
                 _STATE_EXEC_COMMAND_INVALID = -EINVAL,
         } state;
 
-        assert(s);
         assert(key);
         assert(value);
 
@@ -3161,10 +3152,9 @@ int service_deserialize_exec_command(
 }
 
 static int service_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
-        Service *s = SERVICE(u);
+        Service *s = ASSERT_PTR(SERVICE(u));
         int r;
 
-        assert(u);
         assert(key);
         assert(value);
         assert(fds);
@@ -3398,13 +3388,12 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
 }
 
 static UnitActiveState service_active_state(Unit *u) {
+        Service *s = ASSERT_PTR(SERVICE(u));
         const UnitActiveState *table;
 
-        assert(u);
-
-        table = SERVICE(u)->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table;
+        table = s->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table;
 
-        return table[SERVICE(u)->state];
+        return table[s->state];
 }
 
 static const char *service_sub_state_to_string(Unit *u) {
@@ -3414,9 +3403,7 @@ static const char *service_sub_state_to_string(Unit *u) {
 }
 
 static bool service_may_gc(Unit *u) {
-        Service *s = SERVICE(u);
-
-        assert(s);
+        Service *s = ASSERT_PTR(SERVICE(u));
 
         /* Never clean up services that still have a process around, even if the service is formally dead. Note that
          * unit_may_gc() already checked our cgroup for us, we just check our two additional PIDs, too, in case they
@@ -3437,6 +3424,7 @@ static bool service_may_gc(Unit *u) {
 static int service_retry_pid_file(Service *s) {
         int r;
 
+        assert(s);
         assert(s->pid_file);
         assert(IN_SET(s->state, SERVICE_START, SERVICE_START_POST));
 
@@ -3453,6 +3441,8 @@ static int service_retry_pid_file(Service *s) {
 static int service_watch_pid_file(Service *s) {
         int r;
 
+        assert(s);
+
         log_unit_debug(UNIT(s), "Setting watch for PID file %s", s->pid_file_pathspec->path);
 
         r = path_spec_watch(s->pid_file_pathspec, service_dispatch_inotify_io);
@@ -3472,6 +3462,7 @@ static int service_watch_pid_file(Service *s) {
 static int service_demand_pid_file(Service *s) {
         _cleanup_free_ PathSpec *ps = NULL;
 
+        assert(s);
         assert(s->pid_file);
         assert(!s->pid_file_pathspec);
 
@@ -3500,11 +3491,8 @@ static int service_demand_pid_file(Service *s) {
 
 static int service_dispatch_inotify_io(sd_event_source *source, int fd, uint32_t events, void *userdata) {
         PathSpec *p = ASSERT_PTR(userdata);
-        Service *s;
-
-        s = SERVICE(p->unit);
+        Service *s = ASSERT_PTR(SERVICE(p->unit));
 
-        assert(s);
         assert(fd >= 0);
         assert(IN_SET(s->state, SERVICE_START, SERVICE_START_POST));
         assert(s->pid_file_pathspec);
@@ -3530,9 +3518,7 @@ fail:
 }
 
 static int service_dispatch_exec_io(sd_event_source *source, int fd, uint32_t events, void *userdata) {
-        Service *s = SERVICE(userdata);
-
-        assert(s);
+        Service *s = ASSERT_PTR(SERVICE(userdata));
 
         log_unit_debug(UNIT(s), "got exec-fd event");
 
@@ -3583,9 +3569,7 @@ static int service_dispatch_exec_io(sd_event_source *source, int fd, uint32_t ev
 }
 
 static void service_notify_cgroup_empty_event(Unit *u) {
-        Service *s = SERVICE(u);
-
-        assert(u);
+        Service *s = ASSERT_PTR(SERVICE(u));
 
         log_unit_debug(u, "Control group is empty.");
 
@@ -3662,7 +3646,7 @@ static void service_notify_cgroup_empty_event(Unit *u) {
 }
 
 static void service_notify_cgroup_oom_event(Unit *u, bool managed_oom) {
-        Service *s = SERVICE(u);
+        Service *s = ASSERT_PTR(SERVICE(u));
 
         if (managed_oom)
                 log_unit_debug(u, "Process(es) of control group were killed by systemd-oomd.");
@@ -3717,13 +3701,12 @@ static void service_notify_cgroup_oom_event(Unit *u, bool managed_oom) {
 }
 
 static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
+        Service *s = ASSERT_PTR(SERVICE(u));
         bool notify_dbus = true;
-        Service *s = SERVICE(u);
         ServiceResult f;
         ExitClean clean_mode;
         int r;
 
-        assert(s);
         assert(pid >= 0);
 
         /* Oneshot services and non-SERVICE_EXEC_START commands should not be
@@ -4089,9 +4072,8 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 }
 
 static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
-        Service *s = SERVICE(userdata);
+        Service *s = ASSERT_PTR(SERVICE(userdata));
 
-        assert(s);
         assert(source == s->timer_event_source);
 
         switch (s->state) {
@@ -4288,10 +4270,9 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
 }
 
 static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata) {
-        Service *s = SERVICE(userdata);
+        Service *s = ASSERT_PTR(SERVICE(userdata));
         usec_t watchdog_usec;
 
-        assert(s);
         assert(source == s->watchdog_event_source);
 
         watchdog_usec = service_get_watchdog_usec(s);
@@ -4309,6 +4290,8 @@ static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void
 }
 
 static void service_force_watchdog(Service *s) {
+        assert(s);
+
         if (!UNIT(s)->manager->service_watchdogs)
                 return;
 
@@ -4599,10 +4582,12 @@ static void service_notify_message(
 }
 
 static int service_get_timeout(Unit *u, usec_t *timeout) {
-        Service *s = SERVICE(u);
+        Service *s = ASSERT_PTR(SERVICE(u));
         uint64_t t;
         int r;
 
+        assert(timeout);
+
         if (!s->timer_event_source)
                 return 0;
 
@@ -4617,7 +4602,7 @@ static int service_get_timeout(Unit *u, usec_t *timeout) {
 }
 
 static usec_t service_get_timeout_start_usec(Unit *u) {
-        Service *s = SERVICE(ASSERT_PTR(u));
+        Service *s = ASSERT_PTR(SERVICE(u));
         return s->timeout_start_usec;
 }
 
@@ -4637,16 +4622,14 @@ static bool pick_up_pid_from_bus_name(Service *s) {
 }
 
 static int bus_name_pid_lookup_callback(sd_bus_message *reply, void *userdata, sd_bus_error *ret_error) {
+        Service *s = ASSERT_PTR(SERVICE(userdata));
         _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
         const sd_bus_error *e;
-        Unit *u = ASSERT_PTR(userdata);
         uint32_t pid;
-        Service *s;
         int r;
 
         assert(reply);
 
-        s = SERVICE(u);
         s->bus_name_pid_lookup_slot = sd_bus_slot_unref(s->bus_name_pid_lookup_slot);
 
         if (!s->bus_name || !pick_up_pid_from_bus_name(s))
@@ -4671,7 +4654,7 @@ static int bus_name_pid_lookup_callback(sd_bus_message *reply, void *userdata, s
                 return 1;
         }
 
-        log_unit_debug(u, "D-Bus name %s is now owned by process " PID_FMT, s->bus_name, pidref.pid);
+        log_unit_debug(UNIT(s), "D-Bus name %s is now owned by process " PID_FMT, s->bus_name, pidref.pid);
 
         (void) service_set_main_pidref(s, &pidref);
         (void) unit_watch_pidref(UNIT(s), &s->main_pid, /* exclusive= */ false);
@@ -4679,12 +4662,9 @@ static int bus_name_pid_lookup_callback(sd_bus_message *reply, void *userdata, s
 }
 
 static void service_bus_name_owner_change(Unit *u, const char *new_owner) {
-
-        Service *s = SERVICE(u);
+        Service *s = ASSERT_PTR(SERVICE(u));
         int r;
 
-        assert(s);
-
         if (new_owner)
                 log_unit_debug(u, "D-Bus name %s now owned by %s", s->bus_name, new_owner);
         else
@@ -4786,9 +4766,7 @@ int service_set_socket_fd(
 }
 
 static void service_reset_failed(Unit *u) {
-        Service *s = SERVICE(u);
-
-        assert(s);
+        Service *s = ASSERT_PTR(SERVICE(u));
 
         if (s->state == SERVICE_FAILED)
                 service_set_state(s, service_determine_dead_state(s));
@@ -4814,9 +4792,7 @@ static PidRef* service_control_pid(Unit *u) {
 }
 
 static bool service_needs_console(Unit *u) {
-        Service *s = SERVICE(u);
-
-        assert(s);
+        Service *s = ASSERT_PTR(SERVICE(u));
 
         /* We provide our own implementation of this here, instead of relying of the generic implementation
          * unit_needs_console() provides, since we want to return false if we are in SERVICE_EXITED state. */
@@ -4844,9 +4820,7 @@ static bool service_needs_console(Unit *u) {
 }
 
 static int service_exit_status(Unit *u) {
-        Service *s = SERVICE(u);
-
-        assert(u);
+        Service *s = ASSERT_PTR(SERVICE(u));
 
         if (s->main_exec_status.pid <= 0 ||
             !dual_timestamp_is_set(&s->main_exec_status.exit_timestamp))
@@ -4859,20 +4833,17 @@ static int service_exit_status(Unit *u) {
 }
 
 static const char* service_status_text(Unit *u) {
-        Service *s = SERVICE(u);
-
-        assert(s);
+        Service *s = ASSERT_PTR(SERVICE(u));
 
         return s->status_text;
 }
 
 static int service_clean(Unit *u, ExecCleanMask mask) {
+        Service *s = ASSERT_PTR(SERVICE(u));
         _cleanup_strv_free_ char **l = NULL;
         bool may_clean_fdstore = false;
-        Service *s = SERVICE(u);
         int r;
 
-        assert(s);
         assert(mask != 0);
 
         if (!IN_SET(s->state, SERVICE_DEAD, SERVICE_DEAD_RESOURCES_PINNED))
@@ -4928,11 +4899,10 @@ fail:
 }
 
 static int service_can_clean(Unit *u, ExecCleanMask *ret) {
-        Service *s = SERVICE(u);
+        Service *s = ASSERT_PTR(SERVICE(u));
         ExecCleanMask mask = 0;
         int r;
 
-        assert(s);
         assert(ret);
 
         r = exec_context_get_clean_mask(&s->exec_context, &mask);
@@ -4946,10 +4916,12 @@ static int service_can_clean(Unit *u, ExecCleanMask *ret) {
         return 0;
 }
 
-static const char *service_finished_job(Unit *u, JobType t, JobResult result) {
+static const char* service_finished_job(Unit *u, JobType t, JobResult result) {
+        Service *s = ASSERT_PTR(SERVICE(u));
+
         if (t == JOB_START &&
             result == JOB_DONE &&
-            SERVICE(u)->type == SERVICE_ONESHOT)
+            s->type == SERVICE_ONESHOT)
                 return "Finished %s.";
 
         /* Fall back to generic */
@@ -4957,11 +4929,9 @@ static const char *service_finished_job(Unit *u, JobType t, JobResult result) {
 }
 
 static int service_can_start(Unit *u) {
-        Service *s = SERVICE(u);
+        Service *s = ASSERT_PTR(SERVICE(u));
         int r;
 
-        assert(s);
-
         /* Make sure we don't enter a busy loop of some kind. */
         r = unit_test_start_limit(u);
         if (r < 0) {
@@ -4973,7 +4943,7 @@ static int service_can_start(Unit *u) {
 }
 
 static void service_release_resources(Unit *u) {
-        Service *s = SERVICE(ASSERT_PTR(u));
+        Service *s = ASSERT_PTR(SERVICE(u));
 
         /* Invoked by the unit state engine, whenever it realizes that unit is dead and there's no job
          * anymore for it, and it hence is a good idea to release resources */
@@ -5007,14 +4977,9 @@ int service_determine_exec_selinux_label(Service *s, char **ret) {
 
         /* Returns the SELinux label used for execution of the main service binary */
 
-        if (s->exec_context.selinux_context) { /* Prefer the explicitly configured label if there is one */
-                char *con = strdup(s->exec_context.selinux_context);
-                if (!con)
-                        return -ENOMEM;
-
-                *ret = con;
-                return 0;
-        }
+        if (s->exec_context.selinux_context)
+                /* Prefer the explicitly configured label if there is one */
+                return strdup_to(ret, s->exec_context.selinux_context);
 
         if (s->exec_context.root_image ||
             s->exec_context.n_extension_images > 0 ||
index c38f326cba419f7f8dee4ac8c6b67586115ccf73..63ea1758b0867dd971a81bae3b4c3f4dd6d411cd 100644 (file)
@@ -29,6 +29,7 @@ static void slice_init(Unit *u) {
 
 static void slice_set_state(Slice *t, SliceState state) {
         SliceState old_state;
+
         assert(t);
 
         if (t->state != state)
@@ -47,12 +48,10 @@ static void slice_set_state(Slice *t, SliceState state) {
 }
 
 static int slice_add_parent_slice(Slice *s) {
-        Unit *u = UNIT(s);
+        Unit *u = UNIT(ASSERT_PTR(s));
         _cleanup_free_ char *a = NULL;
         int r;
 
-        assert(s);
-
         if (UNIT_GET_SLICE(u))
                 return 0;
 
@@ -151,10 +150,9 @@ static int slice_load_system_slice(Unit *u) {
 }
 
 static int slice_load(Unit *u) {
-        Slice *s = SLICE(u);
+        Slice *s = ASSERT_PTR(SLICE(u));
         int r;
 
-        assert(s);
         assert(u->load_state == UNIT_STUB);
 
         r = slice_load_root_slice(u);
@@ -196,36 +194,35 @@ static int slice_load(Unit *u) {
 }
 
 static int slice_coldplug(Unit *u) {
-        Slice *t = SLICE(u);
+        Slice *s = ASSERT_PTR(SLICE(u));
 
-        assert(t);
-        assert(t->state == SLICE_DEAD);
+        assert(s->state == SLICE_DEAD);
 
-        if (t->deserialized_state != t->state)
-                slice_set_state(t, t->deserialized_state);
+        if (s->deserialized_state != s->state)
+                slice_set_state(s, s->deserialized_state);
 
         return 0;
 }
 
 static void slice_dump(Unit *u, FILE *f, const char *prefix) {
-        Slice *t = SLICE(u);
+        Slice *s = ASSERT_PTR(SLICE(u));
 
-        assert(t);
+        assert(s);
         assert(f);
+        assert(prefix);
 
         fprintf(f,
                 "%sSlice State: %s\n",
-                prefix, slice_state_to_string(t->state));
+                prefix, slice_state_to_string(s->state));
 
-        cgroup_context_dump(UNIT(t), f, prefix);
+        cgroup_context_dump(u, f, prefix);
 }
 
 static int slice_start(Unit *u) {
-        Slice *t = SLICE(u);
+        Slice *s = ASSERT_PTR(SLICE(u));
         int r;
 
-        assert(t);
-        assert(t->state == SLICE_DEAD);
+        assert(s->state == SLICE_DEAD);
 
         r = unit_acquire_invocation_id(u);
         if (r < 0)
@@ -234,27 +231,25 @@ static int slice_start(Unit *u) {
         (void) unit_realize_cgroup(u);
         (void) unit_reset_accounting(u);
 
-        slice_set_state(t, SLICE_ACTIVE);
+        slice_set_state(s, SLICE_ACTIVE);
         return 1;
 }
 
 static int slice_stop(Unit *u) {
-        Slice *t = SLICE(u);
+        Slice *s = ASSERT_PTR(SLICE(u));
 
-        assert(t);
-        assert(t->state == SLICE_ACTIVE);
+        assert(s->state == SLICE_ACTIVE);
 
         /* We do not need to destroy the cgroup explicitly,
          * unit_notify() will do that for us anyway. */
 
-        slice_set_state(t, SLICE_DEAD);
+        slice_set_state(s, SLICE_DEAD);
         return 1;
 }
 
 static int slice_serialize(Unit *u, FILE *f, FDSet *fds) {
-        Slice *s = SLICE(u);
+        Slice *s = ASSERT_PTR(SLICE(u));
 
-        assert(s);
         assert(f);
         assert(fds);
 
@@ -264,9 +259,8 @@ static int slice_serialize(Unit *u, FILE *f, FDSet *fds) {
 }
 
 static int slice_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
-        Slice *s = SLICE(u);
+        Slice *s = ASSERT_PTR(SLICE(u));
 
-        assert(u);
         assert(key);
         assert(value);
         assert(fds);
@@ -276,26 +270,26 @@ static int slice_deserialize_item(Unit *u, const char *key, const char *value, F
 
                 state = slice_state_from_string(value);
                 if (state < 0)
-                        log_debug("Failed to parse state value %s", value);
+                        log_unit_debug(u, "Failed to parse state: %s", value);
                 else
                         s->deserialized_state = state;
 
         } else
-                log_debug("Unknown serialization key '%s'", key);
+                log_unit_debug(u, "Unknown serialization key: %s", key);
 
         return 0;
 }
 
 static UnitActiveState slice_active_state(Unit *u) {
-        assert(u);
+        Slice *s = ASSERT_PTR(SLICE(u));
 
-        return state_translation_table[SLICE(u)->state];
+        return state_translation_table[s->state];
 }
 
 static const char *slice_sub_state_to_string(Unit *u) {
-        assert(u);
+        Slice *s = ASSERT_PTR(SLICE(u));
 
-        return slice_state_to_string(SLICE(u)->state);
+        return slice_state_to_string(s->state);
 }
 
 static int slice_make_perpetual(Manager *m, const char *name, Unit **ret) {
index 9f9de2918791f79edee70b0b8e47f3677cebeb65..cc986ddd3fa6607510a52ddeaf5d608b9611d88e 100644 (file)
@@ -154,11 +154,9 @@ void socket_free_ports(Socket *s) {
 }
 
 static void socket_done(Unit *u) {
-        Socket *s = SOCKET(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
         SocketPeer *p;
 
-        assert(s);
-
         socket_free_ports(s);
 
         while ((p = set_steal_first(s->peers_by_address)))
@@ -254,6 +252,7 @@ static int socket_add_device_dependencies(Socket *s) {
 
 static int socket_add_default_dependencies(Socket *s) {
         int r;
+
         assert(s);
 
         if (!UNIT(s)->default_dependencies)
@@ -274,6 +273,7 @@ static int socket_add_default_dependencies(Socket *s) {
 
 static bool socket_has_exec(Socket *s) {
         unsigned i;
+
         assert(s);
 
         for (i = 0; i < _SOCKET_EXEC_COMMAND_MAX; i++)
@@ -284,11 +284,9 @@ static bool socket_has_exec(Socket *s) {
 }
 
 static int socket_add_extras(Socket *s) {
-        Unit *u = UNIT(s);
+        Unit *u = UNIT(ASSERT_PTR(s));
         int r;
 
-        assert(s);
-
         /* Pick defaults for the trigger limit, if nothing was explicitly configured. We pick a relatively high limit
          * in Accept=yes mode, and a lower limit for Accept=no. Reason: in Accept=yes mode we are invoking accept()
          * ourselves before the trigger limit can hit, thus incoming connections are taken off the socket queue quickly
@@ -451,10 +449,9 @@ static int peer_address_compare_func(const SocketPeer *x, const SocketPeer *y) {
 DEFINE_PRIVATE_HASH_OPS(peer_address_hash_ops, SocketPeer, peer_address_hash_func, peer_address_compare_func);
 
 static int socket_load(Unit *u) {
-        Socket *s = SOCKET(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
         int r;
 
-        assert(u);
         assert(u->load_state == UNIT_STUB);
 
         r = unit_load_fragment_and_dropin(u, true);
@@ -510,8 +507,8 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **ret) {
         }, *i;
         int r;
 
-        assert(fd >= 0);
         assert(s);
+        assert(fd >= 0);
         assert(ret);
 
         if (getpeername(fd, &key.peer.sa, &key.peer_salen) < 0)
@@ -571,10 +568,9 @@ static const char* listen_lookup(int family, int type) {
 }
 
 static void socket_dump(Unit *u, FILE *f, const char *prefix) {
-        Socket *s = SOCKET(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
         const char *prefix2, *str;
 
-        assert(s);
         assert(f);
 
         prefix = strempty(prefix);
@@ -1305,6 +1301,9 @@ static int socket_symlink(Socket *s) {
 static int usbffs_write_descs(int fd, Service *s) {
         int r;
 
+        assert(fd >= 0);
+        assert(s);
+
         if (!s->usb_function_descriptors || !s->usb_function_strings)
                 return -EINVAL;
 
@@ -1376,6 +1375,9 @@ int socket_load_service_unit(Socket *s, int cfd, Unit **ret) {
          * instance name.
          */
 
+        assert(s);
+        assert(ret);
+
         if (UNIT_ISSET(s->service)) {
                 *ret = UNIT_DEREF(s->service);
                 return 0;
@@ -1801,6 +1803,7 @@ static int socket_check_open(Socket *s) {
 
 static void socket_set_state(Socket *s, SocketState state) {
         SocketState old_state;
+
         assert(s);
 
         if (s->state != state)
@@ -1837,10 +1840,9 @@ static void socket_set_state(Socket *s, SocketState state) {
 }
 
 static int socket_coldplug(Unit *u) {
-        Socket *s = SOCKET(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
         int r;
 
-        assert(s);
         assert(s->state == SOCKET_DEAD);
 
         if (s->deserialized_state == s->state)
@@ -1897,7 +1899,6 @@ static int socket_coldplug(Unit *u) {
 }
 
 static int socket_spawn(Socket *s, ExecCommand *c, PidRef *ret_pid) {
-
         _cleanup_(exec_params_shallow_clear) ExecParameters exec_params = EXEC_PARAMETERS_INIT(
                         EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN);
         _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
@@ -2033,6 +2034,7 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f);
 
 static void socket_enter_stop_post(Socket *s, SocketResult f) {
         int r;
+
         assert(s);
 
         if (s->result == SOCKET_SUCCESS)
@@ -2109,6 +2111,7 @@ fail:
 
 static void socket_enter_stop_pre(Socket *s, SocketResult f) {
         int r;
+
         assert(s);
 
         if (s->result == SOCKET_SUCCESS)
@@ -2135,6 +2138,7 @@ static void socket_enter_stop_pre(Socket *s, SocketResult f) {
 
 static void socket_enter_listening(Socket *s) {
         int r;
+
         assert(s);
 
         if (!s->accept && s->flush_pending) {
@@ -2154,6 +2158,7 @@ static void socket_enter_listening(Socket *s) {
 
 static void socket_enter_start_post(Socket *s) {
         int r;
+
         assert(s);
 
         socket_unwatch_control_pid(s);
@@ -2210,6 +2215,7 @@ fail:
 
 static void socket_enter_start_pre(Socket *s) {
         int r;
+
         assert(s);
 
         socket_unwatch_control_pid(s);
@@ -2253,7 +2259,6 @@ static void socket_enter_running(Socket *s, int cfd_in) {
         /* Note that this call takes possession of the connection fd passed. It either has to assign it
          * somewhere or close it. */
         _cleanup_close_ int cfd = cfd_in;
-
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
@@ -2422,11 +2427,9 @@ static void socket_run_next(Socket *s) {
 }
 
 static int socket_start(Unit *u) {
-        Socket *s = SOCKET(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
         int r;
 
-        assert(s);
-
         /* We cannot fulfill this request right now, try again later
          * please! */
         if (IN_SET(s->state,
@@ -2482,9 +2485,7 @@ static int socket_start(Unit *u) {
 }
 
 static int socket_stop(Unit *u) {
-        Socket *s = SOCKET(u);
-
-        assert(s);
+        Socket *s = ASSERT_PTR(SOCKET(u));
 
         /* Already on it */
         if (IN_SET(s->state,
@@ -2519,10 +2520,9 @@ static int socket_stop(Unit *u) {
 }
 
 static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
-        Socket *s = SOCKET(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
         int r;
 
-        assert(u);
         assert(f);
         assert(fds);
 
@@ -2574,10 +2574,9 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
 }
 
 static int socket_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
-        Socket *s = SOCKET(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
         int r;
 
-        assert(u);
         assert(key);
         assert(value);
 
@@ -2814,9 +2813,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
 }
 
 static void socket_distribute_fds(Unit *u, FDSet *fds) {
-        Socket *s = SOCKET(u);
-
-        assert(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
 
         LIST_FOREACH(port, p, s->ports) {
                 int fd;
@@ -2838,15 +2835,15 @@ static void socket_distribute_fds(Unit *u, FDSet *fds) {
 }
 
 static UnitActiveState socket_active_state(Unit *u) {
-        assert(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
 
-        return state_translation_table[SOCKET(u)->state];
+        return state_translation_table[s->state];
 }
 
 static const char *socket_sub_state_to_string(Unit *u) {
-        assert(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
 
-        return socket_state_to_string(SOCKET(u)->state);
+        return socket_state_to_string(s->state);
 }
 
 int socket_port_to_address(const SocketPort *p, char **ret) {
@@ -2884,7 +2881,6 @@ int socket_port_to_address(const SocketPort *p, char **ret) {
 }
 
 const char* socket_port_type_to_string(SocketPort *p) {
-
         assert(p);
 
         switch (p->type) {
@@ -2946,9 +2942,7 @@ SocketType socket_port_type_from_string(const char *s) {
 }
 
 static bool socket_may_gc(Unit *u) {
-        Socket *s = SOCKET(u);
-
-        assert(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
 
         return s->n_connections == 0;
 }
@@ -3086,10 +3080,9 @@ fail:
 }
 
 static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
-        Socket *s = SOCKET(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
         SocketResult f;
 
-        assert(s);
         assert(pid >= 0);
 
         if (pid != s->control_pid.pid)
@@ -3193,9 +3186,8 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 }
 
 static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
-        Socket *s = SOCKET(userdata);
+        Socket *s = ASSERT_PTR(SOCKET(userdata));
 
-        assert(s);
         assert(s->timer_event_source == source);
 
         switch (s->state) {
@@ -3331,9 +3323,8 @@ void socket_connection_unref(Socket *s) {
 }
 
 static void socket_trigger_notify(Unit *u, Unit *other) {
-        Socket *s = SOCKET(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
 
-        assert(u);
         assert(other);
 
         /* Filter out invocations with bogus state */
@@ -3369,7 +3360,7 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
 }
 
 static int socket_get_timeout(Unit *u, usec_t *timeout) {
-        Socket *s = SOCKET(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
         usec_t t;
         int r;
 
@@ -3401,11 +3392,10 @@ static PidRef *socket_control_pid(Unit *u) {
 }
 
 static int socket_clean(Unit *u, ExecCleanMask mask) {
+        Socket *s = ASSERT_PTR(SOCKET(u));
         _cleanup_strv_free_ char **l = NULL;
-        Socket *s = SOCKET(u);
         int r;
 
-        assert(s);
         assert(mask != 0);
 
         if (s->state != SOCKET_DEAD)
@@ -3445,19 +3435,15 @@ fail:
 }
 
 static int socket_can_clean(Unit *u, ExecCleanMask *ret) {
-        Socket *s = SOCKET(u);
-
-        assert(s);
+        Socket *s = ASSERT_PTR(SOCKET(u));
 
         return exec_context_get_clean_mask(&s->exec_context, ret);
 }
 
 static int socket_can_start(Unit *u) {
-        Socket *s = SOCKET(u);
+        Socket *s = ASSERT_PTR(SOCKET(u));
         int r;
 
-        assert(s);
-
         r = unit_test_start_limit(u);
         if (r < 0) {
                 socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT);
index 709671561b757c1b3704fc160ca036d8b2b69936..afd067f0e0d5b26da9a4097a9fee35af7c559057 100644 (file)
@@ -68,9 +68,7 @@ static const char *swap_sub_state_to_string(Unit *u) {
 }
 
 static bool swap_may_gc(Unit *u) {
-        Swap *s = SWAP(u);
-
-        assert(s);
+        Swap *s = ASSERT_PTR(SWAP(u));
 
         if (s->from_proc_swaps)
                 return false;
@@ -134,10 +132,9 @@ static int swap_set_devnode(Swap *s, const char *devnode) {
 }
 
 static void swap_init(Unit *u) {
-        Swap *s = SWAP(u);
+        Swap *s = ASSERT_PTR(SWAP(u));
 
-        assert(s);
-        assert(UNIT(s)->load_state == UNIT_STUB);
+        assert(u->load_state == UNIT_STUB);
 
         s->timeout_usec = u->manager->defaults.timeout_start_usec;
 
@@ -156,9 +153,7 @@ static void swap_unwatch_control_pid(Swap *s) {
 }
 
 static void swap_done(Unit *u) {
-        Swap *s = SWAP(u);
-
-        assert(s);
+        Swap *s = ASSERT_PTR(SWAP(u));
 
         swap_unset_proc_swaps(s);
         swap_set_devnode(s, NULL);
@@ -251,6 +246,7 @@ static int swap_verify(Swap *s) {
         _cleanup_free_ char *e = NULL;
         int r;
 
+        assert(s);
         assert(UNIT(s)->load_state == UNIT_LOADED);
 
         r = unit_name_from_path(s->what, ".swap", &e);
@@ -349,25 +345,22 @@ static int swap_add_extras(Swap *s) {
 }
 
 static int swap_load(Unit *u) {
-        Swap *s = SWAP(u);
-        int r, q = 0;
+        Swap *s = ASSERT_PTR(SWAP(u));
+        int r;
 
-        assert(s);
         assert(u->load_state == UNIT_STUB);
 
         /* Load a .swap file */
-        bool fragment_optional = s->from_proc_swaps;
-        r = unit_load_fragment_and_dropin(u, !fragment_optional);
+        r = unit_load_fragment_and_dropin(u, /* fragment_required = */ !s->from_proc_swaps);
 
         /* Add in some extras, and do so either when we successfully loaded something or when /proc/swaps is
          * already active. */
         if (u->load_state == UNIT_LOADED || s->from_proc_swaps)
-                q = swap_add_extras(s);
+                RET_GATHER(r, swap_add_extras(s));
 
         if (r < 0)
                 return r;
-        if (q < 0)
-                return q;
+
         if (u->load_state != UNIT_LOADED)
                 return 0;
 
@@ -381,11 +374,11 @@ static int swap_setup_unit(
                 int priority,
                 bool set_flags) {
 
+        _cleanup_(unit_freep) Unit *new = NULL;
         _cleanup_free_ char *e = NULL;
-        bool delete = false;
-        Unit *u = NULL;
+        Unit *u;
+        Swap *s;
         int r;
-        SwapParameters *p;
 
         assert(m);
         assert(what);
@@ -393,70 +386,59 @@ static int swap_setup_unit(
 
         r = unit_name_from_path(what, ".swap", &e);
         if (r < 0)
-                return log_unit_error_errno(u, r, "Failed to generate unit name from path: %m");
+                return log_error_errno(r, "Failed to generate unit name from path: %m");
 
         u = manager_get_unit(m, e);
-        if (u &&
-            SWAP(u)->from_proc_swaps &&
-            !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
-                return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
-                                       "Swap %s appeared twice with different device paths %s and %s",
-                                       e, SWAP(u)->parameters_proc_swaps.what, what_proc_swaps);
+        if (u) {
+                s = ASSERT_PTR(SWAP(u));
+
+                if (s->from_proc_swaps &&
+                    !path_equal(s->parameters_proc_swaps.what, what_proc_swaps))
+                        return log_unit_error_errno(u, SYNTHETIC_ERRNO(EEXIST),
+                                                    "Swap appeared twice with different device paths %s and %s, refusing.",
+                                                    s->parameters_proc_swaps.what, what_proc_swaps);
+        } else {
+                r = unit_new_for_name(m, sizeof(Swap), e, &new);
+                if (r < 0)
+                        return log_warning_errno(r, "Failed to load swap unit '%s': %m", e);
 
-        if (!u) {
-                delete = true;
+                u = new;
+                s = ASSERT_PTR(SWAP(u));
 
-                r = unit_new_for_name(m, sizeof(Swap), e, &u);
-                if (r < 0) {
-                        log_unit_warning_errno(u, r, "Failed to load swap unit: %m");
-                        goto fail;
-                }
-
-                SWAP(u)->what = strdup(what);
-                if (!SWAP(u)->what) {
-                        r = log_oom();
-                        goto fail;
-                }
+                s->what = strdup(what);
+                if (!s->what)
+                        return log_oom();
 
                 unit_add_to_load_queue(u);
-        } else
-                delete = false;
+        }
 
-        p = &SWAP(u)->parameters_proc_swaps;
+        SwapParameters *p = &s->parameters_proc_swaps;
 
         if (!p->what) {
                 p->what = strdup(what_proc_swaps);
-                if (!p->what) {
-                        r = log_oom();
-                        goto fail;
-                }
+                if (!p->what)
+                        return log_oom();
         }
 
-        /* The unit is definitely around now, mark it as loaded if it was previously referenced but could not be
-         * loaded. After all we can load it now, from the data in /proc/swaps. */
+        /* The unit is definitely around now, mark it as loaded if it was previously referenced but
+         * could not be loaded. After all we can load it now, from the data in /proc/swaps. */
         if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) {
                 u->load_state = UNIT_LOADED;
                 u->load_error = 0;
         }
 
         if (set_flags) {
-                SWAP(u)->is_active = true;
-                SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
+                s->is_active = true;
+                s->just_activated = !s->from_proc_swaps;
         }
 
-        SWAP(u)->from_proc_swaps = true;
+        s->from_proc_swaps = true;
 
         p->priority = priority;
         p->priority_set = true;
 
         unit_add_to_dbus_queue(u);
         return 0;
-
-fail:
-        if (delete)
-                unit_free(u);
-
-        return r;
 }
 
 static void swap_process_new(Manager *m, const char *device, int prio, bool set_flags) {
@@ -537,11 +519,10 @@ static void swap_set_state(Swap *s, SwapState state) {
 }
 
 static int swap_coldplug(Unit *u) {
-        Swap *s = SWAP(u);
+        Swap *s = ASSERT_PTR(SWAP(u));
         SwapState new_state = SWAP_DEAD;
         int r;
 
-        assert(s);
         assert(s->state == SWAP_DEAD);
 
         if (s->deserialized_state != s->state)
@@ -575,10 +556,9 @@ static int swap_coldplug(Unit *u) {
 }
 
 static void swap_dump(Unit *u, FILE *f, const char *prefix) {
-        Swap *s = SWAP(u);
+        Swap *s = ASSERT_PTR(SWAP(u));
         SwapParameters *p;
 
-        assert(s);
         assert(f);
 
         if (s->from_proc_swaps)
@@ -629,7 +609,6 @@ static void swap_dump(Unit *u, FILE *f, const char *prefix) {
 }
 
 static int swap_spawn(Swap *s, ExecCommand *c, PidRef *ret_pid) {
-
         _cleanup_(exec_params_shallow_clear) ExecParameters exec_params = EXEC_PARAMETERS_INIT(
                         EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN);
         _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
@@ -902,9 +881,7 @@ static int swap_start(Unit *u) {
 }
 
 static int swap_stop(Unit *u) {
-        Swap *s = SWAP(u);
-
-        assert(s);
+        Swap *s = ASSERT_PTR(SWAP(u));
 
         switch (s->state) {
 
@@ -938,9 +915,8 @@ static int swap_stop(Unit *u) {
 }
 
 static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
-        Swap *s = SWAP(u);
+        Swap *s = ASSERT_PTR(SWAP(u));
 
-        assert(s);
         assert(f);
         assert(fds);
 
@@ -955,9 +931,8 @@ static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
 }
 
 static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
-        Swap *s = SWAP(u);
+        Swap *s = ASSERT_PTR(SWAP(u));
 
-        assert(s);
         assert(fds);
 
         if (streq(key, "state")) {
@@ -998,10 +973,9 @@ static int swap_deserialize_item(Unit *u, const char *key, const char *value, FD
 }
 
 static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
-        Swap *s = SWAP(u);
+        Swap *s = ASSERT_PTR(SWAP(u));
         SwapResult f;
 
-        assert(s);
         assert(pid >= 0);
 
         if (pid != s->control_pid.pid)
@@ -1075,9 +1049,8 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 }
 
 static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
-        Swap *s = SWAP(userdata);
+        Swap *s = ASSERT_PTR(SWAP(userdata));
 
-        assert(s);
         assert(s->timer_event_source == source);
 
         switch (s->state) {
@@ -1250,12 +1223,10 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
         return swap_process_proc_swaps(m);
 }
 
-static Unit *swap_following(Unit *u) {
-        Swap *s = SWAP(u);
+static Unitswap_following(Unit *u) {
+        Swap *s = ASSERT_PTR(SWAP(u));
         Swap *first = NULL;
 
-        assert(s);
-
         /* If the user configured the swap through /etc/fstab or
          * a device unit, follow that. */
 
@@ -1287,16 +1258,15 @@ static Unit *swap_following(Unit *u) {
         return UNIT(first);
 }
 
-static int swap_following_set(Unit *u, Set **_set) {
-        Swap *s = SWAP(u);
+static int swap_following_set(Unit *u, Set **ret) {
+        Swap *s = ASSERT_PTR(SWAP(u));
         _cleanup_set_free_ Set *set = NULL;
         int r;
 
-        assert(s);
-        assert(_set);
+        assert(ret);
 
         if (LIST_JUST_US(same_devnode, s)) {
-                *_set = NULL;
+                *ret = NULL;
                 return 0;
         }
 
@@ -1310,7 +1280,7 @@ static int swap_following_set(Unit *u, Set **_set) {
                         return r;
         }
 
-        *_set = TAKE_PTR(set);
+        *ret = TAKE_PTR(set);
         return 1;
 }
 
@@ -1411,28 +1381,22 @@ int swap_process_device_new(Manager *m, sd_device *dev) {
 
 int swap_process_device_remove(Manager *m, sd_device *dev) {
         const char *dn;
-        int r;
         Swap *s;
+        int r;
 
         r = sd_device_get_devname(dev, &dn);
         if (r < 0)
                 return 0;
 
-        while ((s = hashmap_get(m->swaps_by_devnode, dn))) {
-                int q;
-
-                q = swap_set_devnode(s, NULL);
-                if (q < 0)
-                        r = q;
-        }
+        r = 0;
+        while ((s = hashmap_get(m->swaps_by_devnode, dn)))
+                RET_GATHER(r, swap_set_devnode(s, NULL));
 
         return r;
 }
 
 static void swap_reset_failed(Unit *u) {
-        Swap *s = SWAP(u);
-
-        assert(s);
+        Swap *s = ASSERT_PTR(SWAP(u));
 
         if (s->state == SWAP_FAILED)
                 swap_set_state(s, SWAP_DEAD);
@@ -1442,13 +1406,10 @@ static void swap_reset_failed(Unit *u) {
 }
 
 static int swap_get_timeout(Unit *u, usec_t *timeout) {
-        Swap *s = SWAP(u);
+        Swap *s = ASSERT_PTR(SWAP(u));
         usec_t t;
         int r;
 
-        assert(s);
-        assert(u);
-
         if (!s->timer_event_source)
                 return 0;
 
@@ -1482,11 +1443,10 @@ static PidRef* swap_control_pid(Unit *u) {
 }
 
 static int swap_clean(Unit *u, ExecCleanMask mask) {
+        Swap *s = ASSERT_PTR(SWAP(u));
         _cleanup_strv_free_ char **l = NULL;
-        Swap *s = SWAP(u);
         int r;
 
-        assert(s);
         assert(mask != 0);
 
         if (s->state != SWAP_DEAD)
@@ -1526,19 +1486,15 @@ fail:
 }
 
 static int swap_can_clean(Unit *u, ExecCleanMask *ret) {
-        Swap *s = SWAP(u);
-
-        assert(s);
+        Swap *s = ASSERT_PTR(SWAP(u));
 
         return exec_context_get_clean_mask(&s->exec_context, ret);
 }
 
 static int swap_can_start(Unit *u) {
-        Swap *s = SWAP(u);
+        Swap *s = ASSERT_PTR(SWAP(u));
         int r;
 
-        assert(s);
-
         r = unit_test_start_limit(u);
         if (r < 0) {
                 swap_enter_dead(s, SWAP_FAILURE_START_LIMIT_HIT);
index 8f2a331f92b9df10cfb1867bb4efb78315df91c3..bbaa5d313c35cc7fff9ffafee9304658d1a1be82 100644 (file)
@@ -70,11 +70,9 @@ static int target_add_default_dependencies(Target *t) {
 }
 
 static int target_load(Unit *u) {
-        Target *t = TARGET(u);
+        Target *t = ASSERT_PTR(TARGET(u));
         int r;
 
-        assert(t);
-
         r = unit_load_fragment_and_dropin(u, true);
         if (r < 0)
                 return r;
@@ -87,9 +85,8 @@ static int target_load(Unit *u) {
 }
 
 static int target_coldplug(Unit *u) {
-        Target *t = TARGET(u);
+        Target *t = ASSERT_PTR(TARGET(u));
 
-        assert(t);
         assert(t->state == TARGET_DEAD);
 
         if (t->deserialized_state != t->state)
@@ -99,10 +96,10 @@ static int target_coldplug(Unit *u) {
 }
 
 static void target_dump(Unit *u, FILE *f, const char *prefix) {
-        Target *t = TARGET(u);
+        Target *t = ASSERT_PTR(TARGET(u));
 
-        assert(t);
         assert(f);
+        assert(prefix);
 
         fprintf(f,
                 "%sTarget State: %s\n",
@@ -110,10 +107,9 @@ static void target_dump(Unit *u, FILE *f, const char *prefix) {
 }
 
 static int target_start(Unit *u) {
-        Target *t = TARGET(u);
+        Target *t = ASSERT_PTR(TARGET(u));
         int r;
 
-        assert(t);
         assert(t->state == TARGET_DEAD);
 
         r = unit_acquire_invocation_id(u);
@@ -125,9 +121,8 @@ static int target_start(Unit *u) {
 }
 
 static int target_stop(Unit *u) {
-        Target *t = TARGET(u);
+        Target *t = ASSERT_PTR(TARGET(u));
 
-        assert(t);
         assert(t->state == TARGET_ACTIVE);
 
         target_set_state(t, TARGET_DEAD);
@@ -135,21 +130,18 @@ static int target_stop(Unit *u) {
 }
 
 static int target_serialize(Unit *u, FILE *f, FDSet *fds) {
-        Target *s = TARGET(u);
+        Target *t = ASSERT_PTR(TARGET(u));
 
-        assert(s);
         assert(f);
         assert(fds);
 
-        (void) serialize_item(f, "state", target_state_to_string(s->state));
+        (void) serialize_item(f, "state", target_state_to_string(t->state));
         return 0;
 }
 
 static int target_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
-        Target *s = TARGET(u);
+        Target *t = ASSERT_PTR(TARGET(u));
 
-        assert(s);
-        assert(u);
         assert(key);
         assert(value);
         assert(fds);
@@ -159,26 +151,26 @@ static int target_deserialize_item(Unit *u, const char *key, const char *value,
 
                 state = target_state_from_string(value);
                 if (state < 0)
-                        log_debug("Failed to parse state value %s", value);
+                        log_unit_debug(u, "Failed to parse state: %s", value);
                 else
-                        s->deserialized_state = state;
+                        t->deserialized_state = state;
 
         } else
-                log_debug("Unknown serialization key '%s'", key);
+                log_unit_debug(u, "Unknown serialization key: %s", key);
 
         return 0;
 }
 
 static UnitActiveState target_active_state(Unit *u) {
-        assert(u);
+        Target *t = ASSERT_PTR(TARGET(u));
 
-        return state_translation_table[TARGET(u)->state];
+        return state_translation_table[t->state];
 }
 
 static const char *target_sub_state_to_string(Unit *u) {
-        assert(u);
+        Target *t = ASSERT_PTR(TARGET(u));
 
-        return target_state_to_string(TARGET(u)->state);
+        return target_state_to_string(t->state);
 }
 
 const UnitVTable target_vtable = {
@@ -213,4 +205,6 @@ const UnitVTable target_vtable = {
                         [JOB_DONE]       = "Stopped target %s.",
                 },
         },
+
+        .notify_supervisor = true,
 };
index 771e134523be69768bf395e379bf547100de1b3a..0c451c020c401583451a25ef17e02352431cf2ce 100644 (file)
@@ -35,9 +35,8 @@ static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
 static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata);
 
 static void timer_init(Unit *u) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
 
-        assert(u);
         assert(u->load_state == UNIT_STUB);
 
         t->next_elapse_monotonic_or_boottime = USEC_INFINITY;
@@ -58,9 +57,7 @@ void timer_free_values(Timer *t) {
 }
 
 static void timer_done(Unit *u) {
-        Timer *t = TIMER(u);
-
-        assert(t);
+        Timer *t = ASSERT_PTR(TIMER(u));
 
         timer_free_values(t);
 
@@ -201,10 +198,9 @@ static uint64_t timer_get_fixed_delay_hash(Timer *t) {
 }
 
 static int timer_load(Unit *u) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
         int r;
 
-        assert(u);
         assert(u->load_state == UNIT_STUB);
 
         r = unit_load_fragment_and_dropin(u, true);
@@ -231,9 +227,12 @@ static int timer_load(Unit *u) {
 }
 
 static void timer_dump(Unit *u, FILE *f, const char *prefix) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
         Unit *trigger;
 
+        assert(f);
+        assert(prefix);
+
         trigger = UNIT_TRIGGER(u);
 
         fprintf(f,
@@ -279,6 +278,7 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) {
 
 static void timer_set_state(Timer *t, TimerState state) {
         TimerState old_state;
+
         assert(t);
 
         if (t->state != state)
@@ -303,9 +303,8 @@ static void timer_set_state(Timer *t, TimerState state) {
 static void timer_enter_waiting(Timer *t, bool time_change);
 
 static int timer_coldplug(Unit *u) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
 
-        assert(t);
         assert(t->state == TIMER_DEAD);
 
         if (t->deserialized_state == t->state)
@@ -634,10 +633,9 @@ fail:
 }
 
 static int timer_start(Unit *u) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
         int r;
 
-        assert(t);
         assert(IN_SET(t->state, TIMER_DEAD, TIMER_FAILED));
 
         r = unit_test_trigger_loaded(u);
@@ -682,9 +680,8 @@ static int timer_start(Unit *u) {
 }
 
 static int timer_stop(Unit *u) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
 
-        assert(t);
         assert(IN_SET(t->state, TIMER_WAITING, TIMER_RUNNING, TIMER_ELAPSED));
 
         timer_enter_dead(t, TIMER_SUCCESS);
@@ -692,9 +689,8 @@ static int timer_stop(Unit *u) {
 }
 
 static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
 
-        assert(u);
         assert(f);
         assert(fds);
 
@@ -711,9 +707,8 @@ static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
 }
 
 static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
 
-        assert(u);
         assert(key);
         assert(value);
         assert(fds);
@@ -747,21 +742,19 @@ static int timer_deserialize_item(Unit *u, const char *key, const char *value, F
 }
 
 static UnitActiveState timer_active_state(Unit *u) {
-        assert(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
 
-        return state_translation_table[TIMER(u)->state];
+        return state_translation_table[t->state];
 }
 
 static const char *timer_sub_state_to_string(Unit *u) {
-        assert(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
 
-        return timer_state_to_string(TIMER(u)->state);
+        return timer_state_to_string(t->state);
 }
 
 static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
-        Timer *t = TIMER(userdata);
-
-        assert(t);
+        Timer *t = ASSERT_PTR(TIMER(userdata));
 
         if (t->state != TIMER_WAITING)
                 return 0;
@@ -772,9 +765,8 @@ static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
 }
 
 static void timer_trigger_notify(Unit *u, Unit *other) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
 
-        assert(u);
         assert(other);
 
         /* Filter out invocations with bogus state */
@@ -812,9 +804,7 @@ static void timer_trigger_notify(Unit *u, Unit *other) {
 }
 
 static void timer_reset_failed(Unit *u) {
-        Timer *t = TIMER(u);
-
-        assert(t);
+        Timer *t = ASSERT_PTR(TIMER(u));
 
         if (t->state == TIMER_FAILED)
                 timer_set_state(t, TIMER_DEAD);
@@ -823,11 +813,9 @@ static void timer_reset_failed(Unit *u) {
 }
 
 static void timer_time_change(Unit *u) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
         usec_t ts;
 
-        assert(u);
-
         if (t->state != TIMER_WAITING)
                 return;
 
@@ -849,9 +837,7 @@ static void timer_time_change(Unit *u) {
 }
 
 static void timer_timezone_change(Unit *u) {
-        Timer *t = TIMER(u);
-
-        assert(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
 
         if (t->state != TIMER_WAITING)
                 return;
@@ -866,10 +852,9 @@ static void timer_timezone_change(Unit *u) {
 }
 
 static int timer_clean(Unit *u, ExecCleanMask mask) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
         int r;
 
-        assert(t);
         assert(mask != 0);
 
         if (t->state != TIMER_DEAD)
@@ -892,9 +877,8 @@ static int timer_clean(Unit *u, ExecCleanMask mask) {
 }
 
 static int timer_can_clean(Unit *u, ExecCleanMask *ret) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
 
-        assert(t);
         assert(ret);
 
         *ret = t->persistent ? EXEC_CLEAN_STATE : 0;
@@ -902,11 +886,9 @@ static int timer_can_clean(Unit *u, ExecCleanMask *ret) {
 }
 
 static int timer_can_start(Unit *u) {
-        Timer *t = TIMER(u);
+        Timer *t = ASSERT_PTR(TIMER(u));
         int r;
 
-        assert(t);
-
         r = unit_test_start_limit(u);
         if (r < 0) {
                 timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
@@ -917,9 +899,8 @@ static int timer_can_start(Unit *u) {
 }
 
 static void activation_details_timer_serialize(ActivationDetails *details, FILE *f) {
-        ActivationDetailsTimer *t = ACTIVATION_DETAILS_TIMER(details);
+        ActivationDetailsTimer *t = ASSERT_PTR(ACTIVATION_DETAILS_TIMER(details));
 
-        assert(details);
         assert(f);
         assert(t);
 
@@ -950,10 +931,9 @@ static int activation_details_timer_deserialize(const char *key, const char *val
 }
 
 static int activation_details_timer_append_env(ActivationDetails *details, char ***strv) {
-        ActivationDetailsTimer *t = ACTIVATION_DETAILS_TIMER(details);
+        ActivationDetailsTimer *t = ASSERT_PTR(ACTIVATION_DETAILS_TIMER(details));
         int r;
 
-        assert(details);
         assert(strv);
         assert(t);
 
@@ -972,10 +952,9 @@ static int activation_details_timer_append_env(ActivationDetails *details, char
 }
 
 static int activation_details_timer_append_pair(ActivationDetails *details, char ***strv) {
-        ActivationDetailsTimer *t = ACTIVATION_DETAILS_TIMER(details);
+        ActivationDetailsTimer *t = ASSERT_PTR(ACTIVATION_DETAILS_TIMER(details));
         int r;
 
-        assert(details);
         assert(strv);
         assert(t);
 
index 40267531d12b9fb9bcdf939d980693b387dc86c2..f25e2e39861b7f0bda1416caa1fa18bfe53ec6c1 100644 (file)
@@ -91,37 +91,22 @@ static int specifier_cgroup(char specifier, const void *data, const char *root,
 
         bad_specifier(u, specifier);
 
-        if (crt && crt->cgroup_path) {
-                char *n;
-
-                n = strdup(crt->cgroup_path);
-                if (!n)
-                        return -ENOMEM;
-
-                *ret = n;
-                return 0;
-        }
+        if (crt && crt->cgroup_path)
+                return strdup_to(ret, crt->cgroup_path);
 
         return unit_default_cgroup_path(u, ret);
 }
 
 static int specifier_cgroup_root(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
         const Unit *u = ASSERT_PTR(userdata);
-        char *n;
 
         bad_specifier(u, specifier);
 
-        n = strdup(u->manager->cgroup_root);
-        if (!n)
-                return -ENOMEM;
-
-        *ret = n;
-        return 0;
+        return strdup_to(ret, u->manager->cgroup_root);
 }
 
 static int specifier_cgroup_slice(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
         const Unit *u = ASSERT_PTR(userdata), *slice;
-        char *n;
 
         bad_specifier(u, specifier);
 
@@ -130,28 +115,18 @@ static int specifier_cgroup_slice(char specifier, const void *data, const char *
                 CGroupRuntime *crt = unit_get_cgroup_runtime(slice);
 
                 if (crt && crt->cgroup_path)
-                        n = strdup(crt->cgroup_path);
-                else
-                        return unit_default_cgroup_path(slice, ret);
-        } else
-                n = strdup(u->manager->cgroup_root);
-        if (!n)
-                return -ENOMEM;
+                        return strdup_to(ret, crt->cgroup_path);
 
-        *ret = n;
-        return 0;
+                return unit_default_cgroup_path(slice, ret);
+        }
+
+        return strdup_to(ret, u->manager->cgroup_root);
 }
 
 static int specifier_special_directory(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
         const Unit *u = ASSERT_PTR(userdata);
-        char *n;
 
-        n = strdup(u->manager->prefix[PTR_TO_UINT(data)]);
-        if (!n)
-                return -ENOMEM;
-
-        *ret = n;
-        return 0;
+        return strdup_to(ret, u->manager->prefix[PTR_TO_UINT(data)]);
 }
 
 static int specifier_credentials_dir(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
index 2c6a0b3e5727c0e5c3302881c113a9248e6d20ed..9c0794b886737a0b5bff047d5171805c058fd666 100644 (file)
@@ -2678,12 +2678,14 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
 
                         unit_emit_audit_start(u);
                         manager_send_unit_plymouth(m, u);
+                        manager_send_unit_supervisor(m, u, /* active= */ true);
                 }
 
                 if (UNIT_IS_INACTIVE_OR_FAILED(ns) && !UNIT_IS_INACTIVE_OR_FAILED(os)) {
                         /* This unit just stopped/failed. */
 
                         unit_emit_audit_stop(u, ns);
+                        manager_send_unit_supervisor(m, u, /* active= */ false);
                         unit_log_resources(u);
                 }
 
@@ -5336,7 +5338,7 @@ int unit_set_exec_params(Unit *u, ExecParameters *p) {
 
         p->runtime_scope = u->manager->runtime_scope;
 
-        r = strdup_or_null(manager_get_confirm_spawn(u->manager), &p->confirm_spawn);
+        r = strdup_to(&p->confirm_spawn, manager_get_confirm_spawn(u->manager));
         if (r < 0)
                 return r;
 
index b1cc2c2d01311f12f91964751ac658e86788263e..7134d362fe11120bea2b4e0d8fbb353b5086c0a3 100644 (file)
@@ -731,6 +731,9 @@ typedef struct UnitVTable {
         /* If true, we'll notify plymouth about this unit */
         bool notify_plymouth;
 
+        /* If true, we'll notify a surrounding VMM/container manager about this unit becoming available */
+        bool notify_supervisor;
+
         /* The audit events to generate on start + stop (or 0 if none shall be generated) */
         int audit_start_message_type;
         int audit_stop_message_type;
index 7e0c98cb7d45016c01c319d2320789287763d9ab..8e2febd5810bffe06927d3f2b492ec2f25553530 100644 (file)
@@ -179,18 +179,12 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
 
                         c = hashmap_get(h, UID_TO_PTR(uid));
                         if (c) {
-
                                 if (t < c->oldest_mtime) {
-                                        char *n;
-
-                                        n = strdup(de->d_name);
-                                        if (!n)
-                                                return log_oom();
-
-                                        free_and_replace(c->oldest_file, n);
+                                        r = free_and_strdup_warn(&c->oldest_file, de->d_name);
+                                        if (r < 0)
+                                                return r;
                                         c->oldest_mtime = t;
                                 }
-
                         } else {
                                 _cleanup_(vacuum_candidate_freep) VacuumCandidate *n = NULL;
 
@@ -198,10 +192,9 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
                                 if (!n)
                                         return log_oom();
 
-                                n->oldest_file = strdup(de->d_name);
-                                if (!n->oldest_file)
-                                        return log_oom();
-
+                                r = free_and_strdup_warn(&n->oldest_file, de->d_name);
+                                if (r < 0)
+                                        return r;
                                 n->oldest_mtime = t;
 
                                 r = hashmap_put(h, UID_TO_PTR(uid), n);
index e4c8c9674c044e26d00c127adb99ab4ee51afabe..b4df9d23c2a4a003174432fe89f2d8297f42a1d0 100644 (file)
@@ -498,13 +498,8 @@ static int mandatory_mount_drop_unapplicable_options(
         assert(where);
         assert(ret_options);
 
-        if (!(*flags & (MOUNT_NOAUTO|MOUNT_NOFAIL|MOUNT_AUTOMOUNT))) {
-                r = strdup_or_null(options, ret_options);
-                if (r < 0)
-                        return r;
-
-                return 0;
-        }
+        if (!(*flags & (MOUNT_NOAUTO|MOUNT_NOFAIL|MOUNT_AUTOMOUNT)))
+                return strdup_to(ret_options, options);
 
         log_debug("Mount '%s' is mandatory, ignoring 'noauto', 'nofail', and 'x-systemd.automount' options.",
                   where);
index 368ce2d9e23d682e4861457799dde28226a80eb6..624cbdb3d33d90847a1d6dc0bee55e4ec2bc268e 100644 (file)
@@ -415,7 +415,7 @@ int bus_home_method_authenticate(
         return 1;
 }
 
-int bus_home_method_update_record(
+int bus_home_update_record(
                 Home *h,
                 sd_bus_message *message,
                 UserRecord *hr,
@@ -487,7 +487,7 @@ int bus_home_method_update(
                         return r;
         }
 
-        return bus_home_method_update_record(h, message, hr, blobs, flags, error);
+        return bus_home_update_record(h, message, hr, blobs, flags, error);
 }
 
 int bus_home_method_resize(
@@ -657,7 +657,7 @@ int bus_home_method_acquire(
                 return r;
 
         /* This operation might not be something we can executed immediately, hence queue it */
-        fd = home_create_fifo(h, please_suspend ? HOME_FIFO_PLEASE_SUSPEND : HOME_FIFO_DONT_SUSPEND);
+        fd = home_create_fifo(h, please_suspend);
         if (fd < 0)
                 return sd_bus_reply_method_errnof(message, fd, "Failed to allocate FIFO for %s: %m", h->user_name);
 
@@ -716,7 +716,7 @@ int bus_home_method_ref(
                 }
         }
 
-        fd = home_create_fifo(h, please_suspend ? HOME_FIFO_PLEASE_SUSPEND : HOME_FIFO_DONT_SUSPEND);
+        fd = home_create_fifo(h, please_suspend);
         if (fd < 0)
                 return sd_bus_reply_method_errnof(message, fd, "Failed to allocate FIFO for %s: %m", h->user_name);
 
@@ -745,51 +745,6 @@ int bus_home_method_release(
         return 1;
 }
 
-int bus_home_method_inhibit_suspend(
-                sd_bus_message *message,
-                void *userdata,
-                sd_bus_error *error) {
-
-        _cleanup_close_ int fd = -EBADF;
-        Home *h = ASSERT_PTR(userdata);
-        HomeState state;
-        int r;
-
-        r = home_verify_polkit_async(
-                        h,
-                        message,
-                        "org.freedesktop.home1.inhibit-suspend",
-                        h->uid,
-                        error);
-        if (r < 0)
-                return r;
-        if (r == 0)
-                return 1; /* Will call us back */
-
-        state = home_get_state(h);
-        switch (state) {
-        case HOME_ABSENT:
-                return sd_bus_error_setf(error, BUS_ERROR_HOME_ABSENT, "Home %s is currently missing or not plugged in.", h->user_name);
-        case HOME_UNFIXATED:
-        case HOME_INACTIVE:
-        case HOME_DIRTY:
-                return sd_bus_error_setf(error, BUS_ERROR_HOME_NOT_ACTIVE, "Home %s not active.", h->user_name);
-        case HOME_LOCKED:
-                return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is currently locked.", h->user_name);
-        default:
-                if (HOME_STATE_IS_ACTIVE(state))
-                        break;
-
-                return sd_bus_error_setf(error, BUS_ERROR_HOME_BUSY, "An operation on home %s is currently being executed.", h->user_name);
-        }
-
-        fd = home_create_fifo(h, HOME_FIFO_INHIBIT_SUSPEND);
-        if (fd < 0)
-                return sd_bus_reply_method_errnof(message, fd, "Failed to allocate FIFO for %s: %m", h->user_name);
-
-        return sd_bus_reply_method_return(message, "h", fd);
-}
-
 /* We map a uid_t as uint32_t bus property, let's ensure this is safe. */
 assert_cc(sizeof(uid_t) == sizeof(uint32_t));
 
@@ -949,11 +904,6 @@ const sd_bus_vtable home_vtable[] = {
                                 bus_home_method_ref,
                                 0),
         SD_BUS_METHOD("Release", NULL, NULL, bus_home_method_release, 0),
-        SD_BUS_METHOD_WITH_ARGS("InhibitSuspend",
-                                SD_BUS_NO_ARGS,
-                                SD_BUS_RESULT("h", send_fd),
-                                bus_home_method_inhibit_suspend,
-                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_VTABLE_END
 };
 
index 9ba2cf1252504ec49d4aebd66acd6e8cb39e3686..1644bc8066a428b191e635b7462adf7174e8b3f1 100644 (file)
@@ -17,7 +17,6 @@ int bus_home_method_remove(sd_bus_message *message, void *userdata, sd_bus_error
 int bus_home_method_fixate(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_home_method_authenticate(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_home_method_update(sd_bus_message *message, void *userdata, sd_bus_error *error);
-int bus_home_method_update_record(Home *home, sd_bus_message *message, UserRecord *hr, Hashmap *blobs, uint64_t flags, sd_bus_error *error);
 int bus_home_method_resize(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_home_method_change_password(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_home_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error);
@@ -25,7 +24,8 @@ int bus_home_method_unlock(sd_bus_message *message, void *userdata, sd_bus_error
 int bus_home_method_acquire(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_home_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_home_method_release(sd_bus_message *message, void *userdata, sd_bus_error *error);
-int bus_home_method_inhibit_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error);
+
+int bus_home_update_record(Home *home, sd_bus_message *message, UserRecord *hr, Hashmap *blobs, uint64_t flags, sd_bus_error *error);
 
 extern const BusObjectImplementation home_object;
 
index edde6fafd3cbb092378068b9e9933e50e9d0c450..09e86f37f36b03f943e18308b6336ba8c9fc8675 100644 (file)
@@ -226,7 +226,6 @@ Home *home_free(Home *h) {
 
         h->ref_event_source_please_suspend = sd_event_source_disable_unref(h->ref_event_source_please_suspend);
         h->ref_event_source_dont_suspend = sd_event_source_disable_unref(h->ref_event_source_dont_suspend);
-        h->inhibit_suspend_event_source = sd_event_source_disable_unref(h->inhibit_suspend_event_source);
 
         h->pending_operations = ordered_set_free(h->pending_operations);
         h->pending_event_source = sd_event_source_disable_unref(h->pending_event_source);
@@ -2707,9 +2706,6 @@ static int on_home_ref_eof(sd_event_source *s, int fd, uint32_t revents, void *u
         if (h->ref_event_source_dont_suspend == s)
                 h->ref_event_source_dont_suspend = sd_event_source_disable_unref(h->ref_event_source_dont_suspend);
 
-        if (h->inhibit_suspend_event_source == s)
-                h->inhibit_suspend_event_source = sd_event_source_disable_unref(h->inhibit_suspend_event_source);
-
         if (home_is_referenced(h))
                 return 0;
 
@@ -2725,42 +2721,25 @@ static int on_home_ref_eof(sd_event_source *s, int fd, uint32_t revents, void *u
         return 0;
 }
 
-int home_create_fifo(Home *h, HomeFifoType type) {
-        static const struct {
-                const char *suffix;
-                const char *description;
-                size_t event_source;
-        } table[_HOME_FIFO_TYPE_MAX] = {
-                [HOME_FIFO_PLEASE_SUSPEND] = {
-                        .suffix = ".please-suspend",
-                        .description = "acquire-ref",
-                        .event_source = offsetof(Home, ref_event_source_please_suspend),
-                },
-                [HOME_FIFO_DONT_SUSPEND] = {
-                        .suffix = ".dont-suspend",
-                        .description = "acquire-ref-dont-suspend",
-                        .event_source = offsetof(Home, ref_event_source_dont_suspend),
-                },
-                [HOME_FIFO_INHIBIT_SUSPEND] = {
-                        .suffix = ".inhibit-suspend",
-                        .description = "inhibit-suspend",
-                        .event_source = offsetof(Home, inhibit_suspend_event_source),
-                },
-        };
-
+int home_create_fifo(Home *h, bool please_suspend) {
         _cleanup_close_ int ret_fd = -EBADF;
-        sd_event_source **evt;
-        const char *fn;
+        sd_event_source **ss;
+        const char *fn, *suffix;
         int r;
 
         assert(h);
-        assert(type >= 0 && type < _HOME_FIFO_TYPE_MAX);
 
-        evt = (sd_event_source**) ((uint8_t*) h + table[type].event_source);
+        if (please_suspend) {
+                suffix = ".please-suspend";
+                ss = &h->ref_event_source_please_suspend;
+        } else {
+                suffix = ".dont-suspend";
+                ss = &h->ref_event_source_dont_suspend;
+        }
 
-        fn = strjoina("/run/systemd/home/", h->user_name, table[type].suffix);
+        fn = strjoina("/run/systemd/home/", h->user_name, suffix);
 
-        if (!*evt) {
+        if (!*ss) {
                 _cleanup_close_ int ref_fd = -EBADF;
 
                 (void) mkdir("/run/systemd/home/", 0755);
@@ -2771,19 +2750,22 @@ int home_create_fifo(Home *h, HomeFifoType type) {
                 if (ref_fd < 0)
                         return log_error_errno(errno, "Failed to open FIFO %s for reading: %m", fn);
 
-                r = sd_event_add_io(h->manager->event, evt, ref_fd, 0, on_home_ref_eof, h);
+                r = sd_event_add_io(h->manager->event, ss, ref_fd, 0, on_home_ref_eof, h);
                 if (r < 0)
                         return log_error_errno(r, "Failed to allocate reference FIFO event source: %m");
 
-                (void) sd_event_source_set_description(*evt, table[type].description);
+                (void) sd_event_source_set_description(*ss, "acquire-ref");
 
-                r = sd_event_source_set_priority(*evt, SD_EVENT_PRIORITY_IDLE-1);
+                /* We need to notice dropped refs before we process new bus requests (which
+                 * might try to obtain new refs) */
+                r = sd_event_source_set_priority(*ss, SD_EVENT_PRIORITY_NORMAL-10);
                 if (r < 0)
                         return r;
 
-                r = sd_event_source_set_io_fd_own(*evt, true);
+                r = sd_event_source_set_io_fd_own(*ss, true);
                 if (r < 0)
                         return log_error_errno(r, "Failed to pass ownership of FIFO event fd to event source: %m");
+
                 TAKE_FD(ref_fd);
         }
 
@@ -2863,10 +2845,8 @@ bool home_is_referenced(Home *h) {
 bool home_shall_suspend(Home *h) {
         assert(h);
 
-        /* We lock the home area on suspend if... */
-        return h->ref_event_source_please_suspend && /* at least one client supports suspend, and... */
-               !h->ref_event_source_dont_suspend && /* no clients lack support for suspend, and... */
-               !h->inhibit_suspend_event_source; /* no client is temporarily inhibiting suspend */
+        /* Suspend if there's at least one client referencing this home directory that wants a suspend and none who does not. */
+        return h->ref_event_source_please_suspend && !h->ref_event_source_dont_suspend;
 }
 
 static int home_dispatch_release(Home *h, Operation *o) {
@@ -3167,7 +3147,6 @@ int home_schedule_operation(Home *h, Operation *o, sd_bus_error *error) {
 
 static int home_get_image_path_seat(Home *h, char **ret) {
         _cleanup_(sd_device_unrefp) sd_device *d = NULL;
-        _cleanup_free_ char *c = NULL;
         const char *ip, *seat;
         struct stat st;
         int r;
@@ -3200,12 +3179,7 @@ static int home_get_image_path_seat(Home *h, char **ret) {
         else if (r < 0)
                 return r;
 
-        c = strdup(seat);
-        if (!c)
-                return -ENOMEM;
-
-        *ret = TAKE_PTR(c);
-        return 0;
+        return strdup_to(ret, seat);
 }
 
 int home_auto_login(Home *h, char ***ret_seats) {
index 0f3d1ce3251b4fb49c4a730b52be616cc0f3d118..7f42461a45df64873e5bd3b265a61ab04b37319e 100644 (file)
@@ -139,17 +139,12 @@ struct Home {
         bool unregister_on_failure;
 
         /* The reading side of a FIFO stored in /run/systemd/home/, the writing side being used for reference
-         * counting. The references dropped to zero as soon as we see EOF. This concept exists thrice: once
-         * for clients that are fine if we lock the home directory on system suspend, once for clients
-         * that are not ok with that, and once for clients that are usually ok with it but temporarily
-         * want to opt-out so that they can implement more advanced behavior on their own. This allows
-         * us to determine for each home whether there are any clients that don't support suspend at this
-         * moment. */
+         * counting. The references dropped to zero as soon as we see EOF. This concept exists twice: once
+         * for clients that are fine if we suspend the home directory on system suspend, and once for clients
+         * that are not ok with that. This allows us to determine for each home whether there are any clients
+         * that support unsuspend. */
         sd_event_source *ref_event_source_please_suspend;
         sd_event_source *ref_event_source_dont_suspend;
-        /* This is distinct from ref_event_source_dont_suspend because it can be obtained from unprivileged
-         * code, and thus we don't count it as a reference on the home area. */
-        sd_event_source *inhibit_suspend_event_source;
 
         /* Any pending operations we still need to execute. These are for operations we want to queue if we
          * can't execute them right-away. */
@@ -215,15 +210,7 @@ int home_killall(Home *h);
 
 int home_augment_status(Home *h, UserRecordLoadFlags flags, UserRecord **ret);
 
-typedef enum {
-        HOME_FIFO_PLEASE_SUSPEND,
-        HOME_FIFO_DONT_SUSPEND,
-        HOME_FIFO_INHIBIT_SUSPEND,
-        _HOME_FIFO_TYPE_MAX,
-        _HOME_FIFO_TYPE_INVALID = -EINVAL,
-} HomeFifoType;
-int home_create_fifo(Home *h, HomeFifoType mode);
-
+int home_create_fifo(Home *h, bool please_suspend);
 int home_schedule_operation(Home *h, Operation *o, sd_bus_error *error);
 
 int home_auto_login(Home *h, char ***ret_seats);
index 1e63012a06f4accc822ad6b4d9e6d8df221a46b9..403a7d0213b40d18353482dac95d0a4cb81df0ca 100644 (file)
@@ -592,7 +592,7 @@ static int method_update_home(sd_bus_message *message, void *userdata, sd_bus_er
         if (!h)
                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_HOME, "No home for user %s known", hr->user_name);
 
-        return bus_home_method_update_record(h, message, hr, blobs, flags, error);
+        return bus_home_update_record(h, message, hr, blobs, flags, error);
 }
 
 static int method_resize_home(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -623,10 +623,6 @@ static int method_release_home(sd_bus_message *message, void *userdata, sd_bus_e
         return generic_home_method(userdata, message, bus_home_method_release, error);
 }
 
-static int method_inhibit_suspend_home(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return generic_home_method(userdata, message, bus_home_method_inhibit_suspend, error);
-}
-
 static int method_lock_all_homes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_(operation_unrefp) Operation *o = NULL;
         bool waiting = false;
@@ -901,12 +897,6 @@ static const sd_bus_vtable manager_vtable[] = {
                                 method_release_home,
                                 0),
 
-        SD_BUS_METHOD_WITH_ARGS("InhibitSuspendHome",
-                                SD_BUS_ARGS("s", user_name),
-                                SD_BUS_RESULT("h", send_fd),
-                                method_inhibit_suspend_home,
-                                SD_BUS_VTABLE_UNPRIVILEGED),
-
         /* An operation that acts on all homes that allow it */
         SD_BUS_METHOD("LockAllHomes", NULL, NULL, method_lock_all_homes, 0),
         SD_BUS_METHOD("DeactivateAllHomes", NULL, NULL, method_deactivate_all_homes, 0),
index 0653eeef784cfda56668cf5ae6d09f2054e76d72..d4eaf1821b4e49988d92b7bfe4a85d832f5fae75 100644 (file)
@@ -991,7 +991,7 @@ static int manager_connect_bus(Manager *m) {
         if (r < 0)
                 return log_error_errno(r, "Failed to request name: %m");
 
-        r = sd_bus_attach_event(m->bus, m->event, 0);
+        r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
         if (r < 0)
                 return log_error_errno(r, "Failed to attach bus to event loop: %m");
 
index 9d86881d1558f8fb2c0cf5df6b0eec264021d71a..8dcb5c5d46c3ea1202b9ded60b7871425b6ce4c6 100644 (file)
@@ -126,7 +126,6 @@ static int probe_file_system_by_fd(
                 sd_id128_t *ret_uuid) {
 
         _cleanup_(blkid_free_probep) blkid_probe b = NULL;
-        _cleanup_free_ char *s = NULL;
         const char *fstype = NULL, *uuid = NULL;
         sd_id128_t id;
         int r;
@@ -168,13 +167,10 @@ static int probe_file_system_by_fd(
         if (r < 0)
                 return r;
 
-        s = strdup(fstype);
-        if (!s)
-                return -ENOMEM;
-
-        *ret_fstype = TAKE_PTR(s);
+        r = strdup_to(ret_fstype, fstype);
+        if (r < 0)
+                return r;
         *ret_uuid = id;
-
         return 0;
 }
 
index 9ac34aea55f67227af4fd5b2008feedf1b1667dc..b8085929b0108a32b989387aed07f24f355556b7 100644 (file)
                        send_interface="org.freedesktop.home1.Manager"
                        send_member="ReleaseHome"/>
 
-                <allow send_destination="org.freedesktop.home1"
-                       send_interface="org.freedesktop.home1.Manager"
-                       send_member="InhibitSuspendHome"/>
-
                 <allow send_destination="org.freedesktop.home1"
                        send_interface="org.freedesktop.home1.Manager"
                        send_member="LockAllHomes"/>
                        send_interface="org.freedesktop.home1.Home"
                        send_member="Release"/>
 
-                <allow send_destination="org.freedesktop.home1"
-                       send_interface="org.freedesktop.home1.Home"
-                       send_member="InhibitSuspend"/>
-
                 <allow receive_sender="org.freedesktop.home1"/>
         </policy>
 
index be32b2e8e4e198dd7256f110d0c7a4b420f9bf73..3b19ed3ed5fc0a99e55964ff09b8111280c8aead 100644 (file)
                 </defaults>
         </action>
 
-        <action id="org.freedesktop.home1.inhibit-suspend">
-                <description gettext-domain="systemd">Inhibit automatic lock of a home area</description>
-                <message gettext-domain="systemd">Authentication is required to inhibit automatic lock of a user's home area.</message>
-                <defaults>
-                        <allow_any>auth_admin_keep</allow_any>
-                        <allow_inactive>auth_admin_keep</allow_inactive>
-                        <allow_active>auth_admin_keep</allow_active>
-                </defaults>
-        </action>
-
         <action id="org.freedesktop.home1.activate-home">
                 <description gettext-domain="systemd">Activate a home area</description>
                 <message gettext-domain="systemd">Authentication is required to activate a user's home area.</message>
index 83a988154feaea05dbceaba327bd3598a723f2b3..82d08803fa5b6b5123c0c425c9385a5709367d93 100644 (file)
@@ -211,7 +211,6 @@ static bool use_dmi_data(void) {
 
 static int get_dmi_data(const char *database_key, const char *regular_key, char **ret) {
         _cleanup_(sd_device_unrefp) sd_device *device = NULL;
-        _cleanup_free_ char *b = NULL;
         const char *s = NULL;
         int r;
 
@@ -227,17 +226,7 @@ static int get_dmi_data(const char *database_key, const char *regular_key, char
         if (!s && regular_key)
                 (void) sd_device_get_property_value(device, regular_key, &s);
 
-        if (!ret)
-                return !!s;
-
-        if (s) {
-                b = strdup(s);
-                if (!b)
-                        return -ENOMEM;
-        }
-
-        *ret = TAKE_PTR(b);
-        return !!s;
+        return strdup_to_full(ret, s);
 }
 
 static int get_hardware_vendor(char **ret) {
@@ -264,23 +253,7 @@ static int get_hardware_firmware_data(const char *sysattr, char **ret) {
 
         (void) sd_device_get_sysattr_value(device, sysattr, &s);
 
-        bool empty = isempty(s);
-
-        if (ret) {
-                if (empty)
-                        *ret = NULL;
-                else {
-                        _cleanup_free_ char *b = NULL;
-
-                        b = strdup(s);
-                        if (!b)
-                                return -ENOMEM;
-
-                        *ret = TAKE_PTR(b);
-                }
-        }
-
-        return !empty;
+        return strdup_to_full(ret, empty_to_null(s));
 }
 
 static int get_hardware_serial(char **ret) {
index 0325add12f4d7f01d3af712b14e1fcb37c2edfad..90d4f5352fd4973424a2918caef1b0faec65dde3 100644 (file)
@@ -24,6 +24,7 @@
 #include "terminal-util.h"
 
 static const char *arg_identifier = NULL;
+static const char *arg_namespace = NULL;
 static int arg_priority = LOG_INFO;
 static int arg_stderr_priority = -1;
 static bool arg_level_prefix = true;
@@ -44,6 +45,7 @@ static int help(void) {
                "  -p --priority=PRIORITY         Set priority value (0..7)\n"
                "     --stderr-priority=PRIORITY  Set priority value (0..7) used for stderr\n"
                "     --level-prefix=BOOL         Control whether level prefix shall be parsed\n"
+               "     --namespace=NAMESPACE       Connect to specified journal namespace\n"
                "\nSee the %s for details.\n",
                program_invocation_short_name,
                ansi_highlight(),
@@ -58,7 +60,8 @@ static int parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_VERSION = 0x100,
                 ARG_STDERR_PRIORITY,
-                ARG_LEVEL_PREFIX
+                ARG_LEVEL_PREFIX,
+                ARG_NAMESPACE,
         };
 
         static const struct option options[] = {
@@ -68,6 +71,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "priority",        required_argument, NULL, 'p'                 },
                 { "stderr-priority", required_argument, NULL, ARG_STDERR_PRIORITY },
                 { "level-prefix",    required_argument, NULL, ARG_LEVEL_PREFIX    },
+                { "namespace",       required_argument, NULL, ARG_NAMESPACE       },
                 {}
         };
 
@@ -91,10 +95,7 @@ static int parse_argv(int argc, char *argv[]) {
                         return version();
 
                 case 't':
-                        if (isempty(optarg))
-                                arg_identifier = NULL;
-                        else
-                                arg_identifier = optarg;
+                        arg_identifier = empty_to_null(optarg);
                         break;
 
                 case 'p':
@@ -117,6 +118,10 @@ static int parse_argv(int argc, char *argv[]) {
                                 return r;
                         break;
 
+                case ARG_NAMESPACE:
+                        arg_namespace = empty_to_null(optarg);
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -137,12 +142,12 @@ static int run(int argc, char *argv[]) {
         if (r <= 0)
                 return r;
 
-        outfd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix);
+        outfd = sd_journal_stream_fd_with_namespace(arg_namespace, arg_identifier, arg_priority, arg_level_prefix);
         if (outfd < 0)
                 return log_error_errno(outfd, "Failed to create stream fd: %m");
 
         if (arg_stderr_priority >= 0 && arg_stderr_priority != arg_priority) {
-                errfd = sd_journal_stream_fd(arg_identifier, arg_stderr_priority, arg_level_prefix);
+                errfd = sd_journal_stream_fd_with_namespace(arg_namespace, arg_identifier, arg_stderr_priority, arg_level_prefix);
                 if (errfd < 0)
                         return log_error_errno(errfd, "Failed to create stream fd: %m");
         }
index 6f83585db5ffb4e2225f18ad29bb11cfe0095fce..15f3f0e025dad71eb6c4c550f7c58982f3c076e8 100644 (file)
@@ -2070,6 +2070,7 @@ static int update_cursor(sd_journal *j) {
 
 typedef struct Context {
         sd_journal *journal;
+        bool has_cursor;
         bool need_seek;
         bool since_seeked;
         bool ellipsized;
@@ -2099,11 +2100,11 @@ static int show(Context *c) {
                                 break;
                 }
 
-                if (arg_until_set && !arg_reverse && (arg_lines < 0 || arg_since_set)) {
-                        /* If --lines= is set, we usually rely on the n_shown to tell us
-                         * when to stop. However, if --since= is set too, we may end up
-                         * having less than --lines= to output. In this case let's also
-                         * check if the entry is in range. */
+                if (arg_until_set && !arg_reverse && (arg_lines < 0 || arg_since_set || c->has_cursor)) {
+                        /* If --lines= is set, we usually rely on the n_shown to tell us when to stop.
+                         * However, if --since= or one of the cursor argument is set too, we may end up
+                         * having less than --lines= to output. In this case let's also check if the entry
+                         * is in range. */
 
                         usec_t usec;
 
@@ -2712,6 +2713,7 @@ static int run(int argc, char *argv[]) {
 
         Context c = {
                 .journal = j,
+                .has_cursor = cursor,
                 .need_seek = need_seek,
                 .since_seeked = since_seeked,
         };
index c66c09719cac10857afb9632afa0d24c6fa4b34d..d443c4b40113acfd5756c061c38f8d1db6160e40 100755 (executable)
@@ -26,8 +26,6 @@ KERNEL_VERSION="${2:?}"
 ENTRY_DIR_ABS="$3"
 KERNEL_IMAGE="$4"
 
-[ "$KERNEL_INSTALL_LAYOUT" = "uki" ] || exit 0
-
 ENTRY_TOKEN="$KERNEL_INSTALL_ENTRY_TOKEN"
 BOOT_ROOT="$KERNEL_INSTALL_BOOT_ROOT"
 
@@ -48,6 +46,8 @@ case "$COMMAND" in
         ;;
 esac
 
+[ "$KERNEL_INSTALL_LAYOUT" = "uki" ] || exit 0
+
 if ! [ -d "$UKI_DIR" ]; then
     [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "creating $UKI_DIR"
     mkdir -p "$UKI_DIR"
index cf1bb5c3af16521b7044c1dcd898a36dcbfd1f14..6581e80656aa7a35c21032b375a420c4159564e4 100644 (file)
@@ -151,37 +151,37 @@ static int context_copy(const Context *source, Context *ret) {
                         return copy.rfd;
         }
 
-        r = strdup_or_null(source->layout_other, &copy.layout_other);
+        r = strdup_to(&copy.layout_other, source->layout_other);
         if (r < 0)
                 return r;
-        r = strdup_or_null(source->conf_root, &copy.conf_root);
+        r = strdup_to(&copy.conf_root, source->conf_root);
         if (r < 0)
                 return r;
-        r = strdup_or_null(source->boot_root, &copy.boot_root);
+        r = strdup_to(&copy.boot_root, source->boot_root);
         if (r < 0)
                 return r;
-        r = strdup_or_null(source->entry_token, &copy.entry_token);
+        r = strdup_to(&copy.entry_token, source->entry_token);
         if (r < 0)
                 return r;
-        r = strdup_or_null(source->entry_dir, &copy.entry_dir);
+        r = strdup_to(&copy.entry_dir, source->entry_dir);
         if (r < 0)
                 return r;
-        r = strdup_or_null(source->version, &copy.version);
+        r = strdup_to(&copy.version, source->version);
         if (r < 0)
                 return r;
-        r = strdup_or_null(source->kernel, &copy.kernel);
+        r = strdup_to(&copy.kernel, source->kernel);
         if (r < 0)
                 return r;
         r = strv_copy_unless_empty(source->initrds, &copy.initrds);
         if (r < 0)
                 return r;
-        r = strdup_or_null(source->initrd_generator, &copy.initrd_generator);
+        r = strdup_to(&copy.initrd_generator, source->initrd_generator);
         if (r < 0)
                 return r;
-        r = strdup_or_null(source->uki_generator, &copy.uki_generator);
+        r = strdup_to(&copy.uki_generator, source->uki_generator);
         if (r < 0)
                 return r;
-        r = strdup_or_null(source->staging_area, &copy.staging_area);
+        r = strdup_to(&copy.staging_area, source->staging_area);
         if (r < 0)
                 return r;
         r = strv_copy_unless_empty(source->plugins, &copy.plugins);
index 8f5707c8e2895053e5b738a18aa161261d2a5d0f..0b2fa9652414e354caaf9f9e7acd1f255c3cc1d6 100644 (file)
@@ -76,6 +76,7 @@ struct sd_dhcp_server {
         char *agent_circuit_id;
         char *agent_remote_id;
 
+        int lease_dir_fd;
         char *lease_file;
 };
 
index 518c1510941b072c1afe696c5d2915314fffa041..7626552811d51c2a33e1eb6b7f2a32608c0d0499 100644 (file)
@@ -38,3 +38,8 @@ int dhcp_server_static_leases_append_json(sd_dhcp_server *server, JsonVariant **
 
 int dhcp_server_save_leases(sd_dhcp_server *server);
 int dhcp_server_load_leases(sd_dhcp_server *server);
+int dhcp_server_leases_file_get_server_address(
+                int dir_fd,
+                const char *path,
+                struct in_addr *ret_address,
+                uint8_t *ret_prefixlen);
index f30ea6353ea911e4817503f534802326c643336e..c8b03781d04921d8939b4bd1d5b81dc125abf602 100644 (file)
@@ -69,7 +69,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
         struct in_addr address = { .s_addr = htobe32(UINT32_C(10) << 24 | UINT32_C(1))};
         _cleanup_free_ uint8_t *duped = NULL;
-        _cleanup_free_ char *lease_file = NULL;
+        _cleanup_close_ int dir_fd = -EBADF;
 
         if (size < sizeof(DHCPMessage))
                 return 0;
@@ -78,12 +78,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
 
         assert_se(duped = memdup(data, size));
 
-        assert_se(mkdtemp_malloc(NULL, &tmpdir) >= 0);
-        assert_se(lease_file = path_join(tmpdir, "leases"));
+        dir_fd = mkdtemp_open(NULL, 0, &tmpdir);
+        assert_se(dir_fd >= 0);
 
         assert_se(sd_dhcp_server_new(&server, 1) >= 0);
         assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
-        assert_se(sd_dhcp_server_set_lease_file(server, lease_file) >= 0);
+        assert_se(sd_dhcp_server_set_lease_file(server, dir_fd, "leases") >= 0);
         server->fd = open("/dev/null", O_RDWR|O_CLOEXEC|O_NOCTTY);
         assert_se(server->fd >= 0);
         assert_se(sd_dhcp_server_configure_pool(server, &address, 24, 0, 0) >= 0);
index f4c7e8d0a47d4d33df88a8005e9c62bc48500c78..2f84d51e651f85b4f9ccd8b5432f2ac7596fa864 100644 (file)
@@ -286,7 +286,7 @@ int dhcp_server_static_leases_append_json(sd_dhcp_server *server, JsonVariant **
 
 int dhcp_server_save_leases(sd_dhcp_server *server) {
         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
-        _cleanup_(unlink_and_freep) char *temp_path = NULL;
+        _cleanup_free_ char *temp_path = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         sd_id128_t boot_id;
         int r;
@@ -307,7 +307,11 @@ int dhcp_server_save_leases(sd_dhcp_server *server) {
         if (r < 0)
                 return r;
 
-        r = json_build(&v, JSON_BUILD_OBJECT(JSON_BUILD_PAIR_ID128("BootID", boot_id)));
+        r = json_build(&v, JSON_BUILD_OBJECT(
+                                JSON_BUILD_PAIR_ID128("BootID", boot_id),
+                                JSON_BUILD_PAIR_IN4_ADDR("Address", &(struct in_addr) { .s_addr = server->address }),
+                                JSON_BUILD_PAIR_UNSIGNED("PrefixLength",
+                                        in4_addr_netmask_to_prefixlen(&(struct in_addr) { .s_addr = server->netmask }))));
         if (r < 0)
                 return r;
 
@@ -315,11 +319,11 @@ int dhcp_server_save_leases(sd_dhcp_server *server) {
         if (r < 0)
                 return r;
 
-        r = mkdir_parents(server->lease_file, 0755);
+        r = mkdirat_parents(server->lease_dir_fd, server->lease_file, 0755);
         if (r < 0)
                 return r;
 
-        r = fopen_temporary(server->lease_file, &f, &temp_path);
+        r = fopen_temporary_at(server->lease_dir_fd, server->lease_file, &f, &temp_path);
         if (r < 0)
                 return r;
 
@@ -327,14 +331,17 @@ int dhcp_server_save_leases(sd_dhcp_server *server) {
 
         r = json_variant_dump(v, JSON_FORMAT_NEWLINE | JSON_FORMAT_FLUSH, f, /* prefix = */ NULL);
         if (r < 0)
-                return r;
+                goto failure;
 
-        r = conservative_rename(temp_path, server->lease_file);
+        r = conservative_renameat(server->lease_dir_fd, temp_path, server->lease_dir_fd, server->lease_file);
         if (r < 0)
-                return r;
+                goto failure;
 
-        temp_path = mfree(temp_path);
         return 0;
+
+failure:
+        (void) unlinkat(server->lease_dir_fd, temp_path, /* flags = */ 0);
+        return r;
 }
 
 static int json_dispatch_dhcp_lease(sd_dhcp_server *server, JsonVariant *v, bool use_boottime) {
@@ -405,37 +412,51 @@ static int json_dispatch_dhcp_lease(sd_dhcp_server *server, JsonVariant *v, bool
 
 typedef struct SavedInfo {
         sd_id128_t boot_id;
+        struct in_addr address;
+        uint8_t prefixlen;
         JsonVariant *leases;
 } SavedInfo;
 
-static int dhcp_server_dispatch_leases(sd_dhcp_server *server, JsonVariant *v) {
-        static const JsonDispatch dispatch_table[] = {
-                { "BootID", JSON_VARIANT_STRING, json_dispatch_id128,         offsetof(SavedInfo, boot_id), JSON_MANDATORY },
-                { "Leases", JSON_VARIANT_ARRAY,  json_dispatch_variant_noref, offsetof(SavedInfo, leases),  JSON_MANDATORY },
-                {}
-        };
+static void saved_info_done(SavedInfo *info) {
+        if (!info)
+                return;
 
-        SavedInfo info = {};
-        sd_id128_t boot_id;
+        json_variant_unref(info->leases);
+}
+
+static int load_leases_file(int dir_fd, const char *path, SavedInfo *ret) {
+        _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
         int r;
 
-        r = json_dispatch(v, dispatch_table, JSON_ALLOW_EXTENSIONS, &info);
-        if (r < 0)
-                return r;
+        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
+        assert(path);
+        assert(ret);
 
-        r = sd_id128_get_boot(&boot_id);
+        r = json_parse_file_at(
+                        /* f = */ NULL,
+                        dir_fd,
+                        path,
+                        /* flags = */ 0,
+                        &v,
+                        /* ret_line = */ NULL,
+                        /* ret_column = */ NULL);
         if (r < 0)
                 return r;
 
-        JsonVariant *i;
-        JSON_VARIANT_ARRAY_FOREACH(i, info.leases)
-                RET_GATHER(r, json_dispatch_dhcp_lease(server, i, /* use_boottime = */ sd_id128_equal(info.boot_id, boot_id)));
+        static const JsonDispatch dispatch_lease_file_table[] = {
+                { "BootID",       JSON_VARIANT_STRING,        json_dispatch_id128,   offsetof(SavedInfo, boot_id),   JSON_MANDATORY },
+                { "Address",      JSON_VARIANT_ARRAY,         json_dispatch_in_addr, offsetof(SavedInfo, address),   JSON_MANDATORY },
+                { "PrefixLength", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint8,   offsetof(SavedInfo, prefixlen), JSON_MANDATORY },
+                { "Leases",       JSON_VARIANT_ARRAY,         json_dispatch_variant, offsetof(SavedInfo, leases),    JSON_MANDATORY },
+                {}
+        };
 
-        return r;
+        return json_dispatch(v, dispatch_lease_file_table, JSON_ALLOW_EXTENSIONS, ret);
 }
 
 int dhcp_server_load_leases(sd_dhcp_server *server) {
-        _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+        _cleanup_(saved_info_done) SavedInfo info = {};
+        sd_id128_t boot_id;
         size_t n, m;
         int r;
 
@@ -445,21 +466,21 @@ int dhcp_server_load_leases(sd_dhcp_server *server) {
         if (!server->lease_file)
                 return 0;
 
-        r = json_parse_file(
-                        /* f = */ NULL,
-                        server->lease_file,
-                        /* flags = */ 0,
-                        &v,
-                        /* ret_line = */ NULL,
-                        /* ret_column = */ NULL);
+        r = load_leases_file(server->lease_dir_fd, server->lease_file, &info);
         if (r == -ENOENT)
                 return 0;
         if (r < 0)
                 return r;
 
+        r = sd_id128_get_boot(&boot_id);
+        if (r < 0)
+                return r;
+
         n = hashmap_size(server->bound_leases_by_client_id);
 
-        r = dhcp_server_dispatch_leases(server, v);
+        JsonVariant *i;
+        JSON_VARIANT_ARRAY_FOREACH(i, info.leases)
+                RET_GATHER(r, json_dispatch_dhcp_lease(server, i, /* use_boottime = */ sd_id128_equal(info.boot_id, boot_id)));
 
         m = hashmap_size(server->bound_leases_by_client_id);
         assert(m >= n);
@@ -467,3 +488,26 @@ int dhcp_server_load_leases(sd_dhcp_server *server) {
 
         return r;
 }
+
+int dhcp_server_leases_file_get_server_address(
+                int dir_fd,
+                const char *path,
+                struct in_addr *ret_address,
+                uint8_t *ret_prefixlen) {
+
+        _cleanup_(saved_info_done) SavedInfo info = {};
+        int r;
+
+        if (!ret_address && !ret_prefixlen)
+                return 0;
+
+        r = load_leases_file(dir_fd, path, &info);
+        if (r < 0)
+                return r;
+
+        if (ret_address)
+                *ret_address = info.address;
+        if (ret_prefixlen)
+                *ret_prefixlen = info.prefixlen;
+        return 0;
+}
index bbe96be83463b87e9bcc71c77064e3b0087669b1..6ec84405d9a279a0b8ad89ee2c0c9f23342cc6f6 100644 (file)
@@ -144,6 +144,7 @@ static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
         free(server->agent_circuit_id);
         free(server->agent_remote_id);
 
+        safe_close(server->lease_dir_fd);
         free(server->lease_file);
 
         free(server->ifname);
@@ -174,6 +175,7 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
                 .default_lease_time = DHCP_DEFAULT_LEASE_TIME_USEC,
                 .max_lease_time = DHCP_MAX_LEASE_TIME_USEC,
                 .rapid_commit = true,
+                .lease_dir_fd = -EBADF,
         };
 
         *ret = TAKE_PTR(server);
@@ -1586,12 +1588,34 @@ int sd_dhcp_server_set_relay_agent_information(
         return 0;
 }
 
-int sd_dhcp_server_set_lease_file(sd_dhcp_server *server, const char *path) {
+int sd_dhcp_server_set_lease_file(sd_dhcp_server *server, int dir_fd, const char *path) {
+        int r;
+
         assert_return(server, -EINVAL);
         assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
 
-        if (path && !path_is_safe(path))
+        if (!path) {
+                /* When NULL, clear the previous assignment. */
+                server->lease_file = mfree(server->lease_file);
+                server->lease_dir_fd = safe_close(server->lease_dir_fd);
+                return 0;
+        }
+
+        if (!path_is_safe(path))
                 return -EINVAL;
 
-        return free_and_strdup(&server->lease_file, path);
+        if (dir_fd < 0 && dir_fd != AT_FDCWD)
+                return -EBADF;
+
+        _cleanup_close_ int fd = -EBADF;
+        fd = fd_reopen(dir_fd, O_CLOEXEC | O_DIRECTORY | O_PATH);
+        if (fd < 0)
+                return fd;
+
+        r = free_and_strdup(&server->lease_file, path);
+        if (r < 0)
+                return r;
+
+        server->lease_dir_fd = TAKE_FD(fd);
+        return 0;
 }
index 22cf48c5f8db7b05c3479edf595d243a360b9a46..d23da4c1515c84cd4e54fea36a117c3478d1f9ad 100644 (file)
@@ -839,4 +839,5 @@ LIBSYSTEMD_256 {
 global:
         sd_bus_creds_get_pidfd_dup;
         sd_bus_creds_new_from_pidfd;
+        sd_journal_stream_fd_with_namespace;
 } LIBSYSTEMD_255;
index 8318373fb24c53e121272c4b2b7c2bad5bb3659e..123629c35608c1174fee1c88e96f0f9767b0ec4d 100644 (file)
@@ -9,7 +9,6 @@
 
 int devname_from_devnum(mode_t mode, dev_t devnum, char **ret) {
         _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
-        _cleanup_free_ char *s = NULL;
         const char *devname;
         int r;
 
@@ -26,15 +25,10 @@ int devname_from_devnum(mode_t mode, dev_t devnum, char **ret) {
         if (r < 0)
                 return r;
 
-        s = strdup(devname);
-        if (!s)
-                return -ENOMEM;
-
-        *ret = TAKE_PTR(s);
-        return 0;
+        return strdup_to(ret, devname);
 }
 
-int device_open_from_devnum(mode_t mode, dev_t devnum, int flags, char **ret) {
+int device_open_from_devnum(mode_t mode, dev_t devnum, int flags, char **ret_devname) {
         _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
         _cleanup_close_ int fd = -EBADF;
         int r;
@@ -47,19 +41,16 @@ int device_open_from_devnum(mode_t mode, dev_t devnum, int flags, char **ret) {
         if (fd < 0)
                 return fd;
 
-        if (ret) {
+        if (ret_devname) {
                 const char *devname;
-                char *s;
 
                 r = sd_device_get_devname(dev, &devname);
                 if (r < 0)
                         return r;
 
-                s = strdup(devname);
-                if (!s)
-                        return -ENOMEM;
-
-                *ret = s;
+                r = strdup_to(ret_devname, devname);
+                if (r < 0)
+                        return r;
         }
 
         return TAKE_FD(fd);
index 534a296715b360c97a75eceb104adf277cac0869..b17993d55404e628169bcc3da72975169dff4e3a 100644 (file)
@@ -100,7 +100,7 @@ static inline int devname_from_stat_rdev(const struct stat *st, char **ret) {
         assert(st);
         return devname_from_devnum(st->st_mode, st->st_rdev, ret);
 }
-int device_open_from_devnum(mode_t mode, dev_t devnum, int flags, char **ret);
+int device_open_from_devnum(mode_t mode, dev_t devnum, int flags, char **ret_devname);
 
 char** device_make_log_fields(sd_device *device);
 
index 826d67371aac27d569e55ce3231b020c75642a12..a0b673f65fc9721e727e5919884f4f32fbd2d36b 100644 (file)
@@ -223,10 +223,7 @@ static int catalog_entry_lang(
                 const char* deflang,
                 char **ret) {
 
-        size_t c;
-        char *z;
-
-        c = strlen(t);
+        size_t c = strlen(t);
         if (c < 2)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "[%s:%u] Language too short.", filename, line);
@@ -243,12 +240,7 @@ static int catalog_entry_lang(
                 log_warning("[%s:%u] language differs from default for file", filename, line);
         }
 
-        z = strdup(t);
-        if (!z)
-                return -ENOMEM;
-
-        *ret = z;
-        return 0;
+        return strdup_to(ret, t);
 }
 
 int catalog_import_file(OrderedHashmap *h, const char *path) {
@@ -588,15 +580,14 @@ static const char *find_id(void *p, sd_id128_t id) {
                 le64toh(f->offset);
 }
 
-int catalog_get(const char* database, sd_id128_t id, char **_text) {
+int catalog_get(const char* database, sd_id128_t id, char **ret_text) {
         _cleanup_close_ int fd = -EBADF;
         void *p = NULL;
-        struct stat st = {};
-        char *text = NULL;
+        struct stat st;
         int r;
         const char *s;
 
-        assert(_text);
+        assert(ret_text);
 
         r = open_mmap(database, &fd, &st, &p);
         if (r < 0)
@@ -608,15 +599,7 @@ int catalog_get(const char* database, sd_id128_t id, char **_text) {
                 goto finish;
         }
 
-        text = strdup(s);
-        if (!text) {
-                r = -ENOMEM;
-                goto finish;
-        }
-
-        *_text = text;
-        r = 0;
-
+        r = strdup_to(ret_text, s);
 finish:
         (void) munmap(p, st.st_size);
 
index df27869fb3281031a560253339b38cdc141a785c..b5a97fa6fbbd9455ad727fada3222b1fc3d65342 100644 (file)
@@ -11,7 +11,7 @@
 
 int catalog_import_file(OrderedHashmap *h, const char *path);
 int catalog_update(const char* database, const char* root, const char* const* dirs);
-int catalog_get(const char* database, sd_id128_t id, char **data);
+int catalog_get(const char* database, sd_id128_t id, char **ret_text);
 int catalog_list(FILE *f, const char* database, bool oneline);
 int catalog_list_items(FILE *f, const char* database, bool oneline, char **items);
 int catalog_file_lang(const char *filename, char **lang);
index be23b2fe75d631f03f032f984ba2f5eb0e020049..650581addf41bee70a18c2c0394180b60393ba95 100644 (file)
@@ -398,20 +398,28 @@ _public_ int sd_journal_perror(const char *message) {
         return fill_iovec_perror_and_send(message, 0, iovec);
 }
 
-_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
+_public_ int sd_journal_stream_fd_with_namespace(
+                const char *name_space,
+                const char *identifier,
+                int priority,
+                int level_prefix) {
+
         _cleanup_close_ int fd = -EBADF;
-        char *header;
-        size_t l;
+        const char *path;
         int r;
 
         assert_return(priority >= 0, -EINVAL);
         assert_return(priority <= 7, -EINVAL);
 
+        path = journal_stream_path(name_space);
+        if (!path)
+                return -EINVAL;
+
         fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
         if (fd < 0)
                 return -errno;
 
-        r = connect_unix_path(fd, AT_FDCWD, "/run/systemd/journal/stdout");
+        r = connect_unix_path(fd, AT_FDCWD, path);
         if (r < 0)
                 return r;
 
@@ -422,6 +430,9 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve
 
         identifier = strempty(identifier);
 
+        char *header;
+        size_t l;
+
         l = strlen(identifier);
         header = newa(char, l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
 
@@ -446,6 +457,10 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve
         return TAKE_FD(fd);
 }
 
+_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
+        return sd_journal_stream_fd_with_namespace(NULL, identifier, priority, level_prefix);
+}
+
 _public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
         int r;
         va_list ap;
index 24315e249b32d9d0f7a88189d487dd98ac0d0305..6fe6325090ec768c08c58af37babfbe1aa33a152 100644 (file)
@@ -2,6 +2,23 @@
 #pragma once
 
 #include <stdbool.h>
+#include <stddef.h>
+
+#include "syslog-util.h"
 
 int journal_fd_nonblock(bool nonblock);
 void close_journal_fd(void);
+
+/* We declare sd_journal_stream_fd() as async-signal-safe. So instead of strjoin(), which calls malloc()
+ * internally, use a macro + alloca(). */
+#define journal_stream_path(log_namespace)                                              \
+        ({                                                                              \
+                const char *_ns = (log_namespace), *_ret;                               \
+                if (!_ns)                                                               \
+                        _ret = "/run/systemd/journal/stdout";                           \
+                else if (log_namespace_name_valid(_ns))                                 \
+                        _ret = strjoina("/run/systemd/journal.", _ns, "/stdout");       \
+                else                                                                    \
+                        _ret = NULL;                                                    \
+                _ret;                                                                   \
+        })
index fba436fbe3f0e1afadb3b86f45c2d3cb7c371989..ef57f156ac5910378b877302106b8b9356416de7 100644 (file)
@@ -1473,17 +1473,6 @@ static void track_file_disposition(sd_journal *j, JournalFile *f) {
                 j->has_persistent_files = true;
 }
 
-static const char *skip_slash(const char *p) {
-
-        if (!p)
-                return NULL;
-
-        while (*p == '/')
-                p++;
-
-        return p;
-}
-
 static int add_any_file(
                 sd_journal *j,
                 int fd,
@@ -1503,7 +1492,7 @@ static int add_any_file(
                         /* If there's a top-level fd defined make the path relative, explicitly, since otherwise
                          * openat() ignores the first argument. */
 
-                        fd = our_fd = openat(j->toplevel_fd, skip_slash(path), O_RDONLY|O_CLOEXEC|O_NONBLOCK);
+                        fd = our_fd = openat(j->toplevel_fd, skip_leading_slash(path), O_RDONLY|O_CLOEXEC|O_NONBLOCK);
                 else
                         fd = our_fd = open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
                 if (fd < 0) {
@@ -1811,7 +1800,7 @@ static int directory_open(sd_journal *j, const char *path, DIR **ret) {
         else
                 /* Open the specified directory relative to the toplevel fd. Enforce that the path specified is
                  * relative, by dropping the initial slash */
-                d = xopendirat(j->toplevel_fd, skip_slash(path), 0);
+                d = xopendirat(j->toplevel_fd, skip_leading_slash(path), 0);
         if (!d)
                 return -errno;
 
index 0489df573b593077547bf1ca3df6324fc4d3e53a..56996596fe13ce07134f498aef25a73ac6503cab 100644 (file)
@@ -735,7 +735,9 @@ int vconsole_convert_to_x11(const VCContext *vc, X11Context *ret) {
 }
 
 int find_converted_keymap(const X11Context *xc, char **ret) {
-        _cleanup_free_ char *n = NULL;
+        _cleanup_free_ char *n = NULL, *p = NULL, *pz = NULL;
+        _cleanup_strv_free_ char **keymap_dirs = NULL;
+        int r;
 
         assert(xc);
         assert(!isempty(xc->layout));
@@ -748,18 +750,29 @@ int find_converted_keymap(const X11Context *xc, char **ret) {
         if (!n)
                 return -ENOMEM;
 
-        NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
-                _cleanup_free_ char *p = NULL, *pz = NULL;
+        p = strjoin("xkb/", n, ".map");
+        pz = strjoin("xkb/", n, ".map.gz");
+        if (!p || !pz)
+                return -ENOMEM;
+
+        r = keymap_directories(&keymap_dirs);
+        if (r < 0)
+                return r;
+
+        STRV_FOREACH(dir, keymap_dirs) {
+                _cleanup_close_ int dir_fd = -EBADF;
                 bool uncompressed;
 
-                p = strjoin(dir, "xkb/", n, ".map");
-                pz = strjoin(dir, "xkb/", n, ".map.gz");
-                if (!p || !pz)
-                        return -ENOMEM;
+                dir_fd = open(*dir, O_CLOEXEC | O_DIRECTORY | O_PATH);
+                if (dir_fd < 0) {
+                        if (errno != ENOENT)
+                                log_debug_errno(errno, "Failed to open %s, ignoring: %m", *dir);
+                        continue;
+                }
 
-                uncompressed = access(p, F_OK) == 0;
-                if (uncompressed || access(pz, F_OK) == 0) {
-                        log_debug("Found converted keymap %s at %s", n, uncompressed ? p : pz);
+                uncompressed = faccessat(dir_fd, p, F_OK, 0) >= 0;
+                if (uncompressed || faccessat(dir_fd, pz, F_OK, 0) >= 0) {
+                        log_debug("Found converted keymap %s at %s/%s", n, *dir, uncompressed ? p : pz);
                         *ret = TAKE_PTR(n);
                         return 1;
                 }
index 5758a2624c791107620cac0a8cfe01e815f98ad0..c0d104578d468f7ab1cc43f6146127e361019a58 100644 (file)
@@ -158,11 +158,7 @@ static int process_locale_list_item(
                 if (new_locale[p])
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale variable %s set twice, refusing.", name);
 
-                new_locale[p] = strdup(e);
-                if (!new_locale[p])
-                        return -ENOMEM;
-
-                return 0;
+                return strdup_to(&new_locale[p], e);
         }
 
         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale assignment %s not valid, refusing.", assignment);
index 63253bd9dcf3c04b7e07e60f6dc2a671ccacacd8..8236dc2dc839fa848a314f35361aa76456538b8b 100644 (file)
@@ -1028,7 +1028,6 @@ static int get_bus_path_by_id(
 
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        _cleanup_free_ char *p = NULL;
         const char *path;
         int r;
 
@@ -1047,12 +1046,7 @@ static int get_bus_path_by_id(
         if (r < 0)
                 return bus_log_parse_error(r);
 
-        p = strdup(path);
-        if (!p)
-                return log_oom();
-
-        *ret = TAKE_PTR(p);
-        return 0;
+        return strdup_to(ret, path);
 }
 
 static int show_session(int argc, char *argv[], void *userdata) {
index 27d4f72b4c009494cb594b788bf5f9edd23a2723..c342522e3f82dd992618bb2ec10c6aa28d510c69 100644 (file)
@@ -989,53 +989,41 @@ static int create_session(
                 user->gc_mode = USER_GC_BY_PIN;
 
         if (!isempty(tty)) {
-                session->tty = strdup(tty);
-                if (!session->tty) {
-                        r = -ENOMEM;
+                r = strdup_to(&session->tty, tty);
+                if (r < 0)
                         goto fail;
-                }
 
                 session->tty_validity = TTY_FROM_PAM;
         }
 
         if (!isempty(display)) {
-                session->display = strdup(display);
-                if (!session->display) {
-                        r = -ENOMEM;
+                r = strdup_to(&session->display, display);
+                if (r < 0)
                         goto fail;
-                }
         }
 
         if (!isempty(remote_user)) {
-                session->remote_user = strdup(remote_user);
-                if (!session->remote_user) {
-                        r = -ENOMEM;
+                r = strdup_to(&session->remote_user, remote_user);
+                if (r < 0)
                         goto fail;
-                }
         }
 
         if (!isempty(remote_host)) {
-                session->remote_host = strdup(remote_host);
-                if (!session->remote_host) {
-                        r = -ENOMEM;
+                r = strdup_to(&session->remote_host, remote_host);
+                if (r < 0)
                         goto fail;
-                }
         }
 
         if (!isempty(service)) {
-                session->service = strdup(service);
-                if (!session->service) {
-                        r = -ENOMEM;
+                r = strdup_to(&session->service, service);
+                if (r < 0)
                         goto fail;
-                }
         }
 
         if (!isempty(desktop)) {
-                session->desktop = strdup(desktop);
-                if (!session->desktop) {
-                        r = -ENOMEM;
+                r = strdup_to(&session->desktop, desktop);
+                if (r < 0)
                         goto fail;
-                }
         }
 
         if (seat) {
index cd5c0ec82dbb7a512e7d4adee67e80adf93dbbb3..c924f1e0cad21303cf04ebabe7a12ac4f896bfe6 100644 (file)
@@ -314,11 +314,7 @@ static int session_device_verify(SessionDevice *sd) {
         if (sd->device->seat != sd->session->seat)
                 return -EPERM;
 
-        sd->node = strdup(node);
-        if (!sd->node)
-                return -ENOMEM;
-
-        return 0;
+        return strdup_to(&sd->node, node);
 }
 
 int session_device_new(Session *s, dev_t dev, bool open_device, SessionDevice **ret) {
index bab3719a495b8bc97b94137fe512a237982ce3a6..42b7fef720466e5ca0e4149f9973c6e60193e72a 100644 (file)
@@ -121,19 +121,14 @@ static OutputFlags get_output_flags(void) {
 static int call_get_os_release(sd_bus *bus, const char *method, const char *name, const char *query, ...) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        const char *k, *v, **query_res = NULL;
-        size_t count = 0, awaited_args = 0;
         va_list ap;
         int r;
 
         assert(bus);
+        assert(method);
         assert(name);
         assert(query);
 
-        NULSTR_FOREACH(iter, query)
-                awaited_args++;
-        query_res = newa0(const char *, awaited_args);
-
         r = bus_call_method(bus, bus_machine_mgr, method, &error, &reply, "s", name);
         if (r < 0)
                 return log_debug_errno(r, "Failed to call '%s()': %s", method, bus_error_message(&error, r));
@@ -142,14 +137,23 @@ static int call_get_os_release(sd_bus *bus, const char *method, const char *name
         if (r < 0)
                 return bus_log_parse_error(r);
 
+        const char **res;
+        size_t n_fields = 0;
+
+        NULSTR_FOREACH(i, query)
+                n_fields++;
+
+        res = newa0(const char*, n_fields);
+
+        const char *k, *v;
         while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) {
-                count = 0;
-                NULSTR_FOREACH(iter, query) {
-                        if (streq(k, iter)) {
-                                query_res[count] = v;
+                size_t c = 0;
+                NULSTR_FOREACH(i, query) {
+                        if (streq(i, k)) {
+                                res[c] = v;
                                 break;
                         }
-                        count++;
+                        c++;
                 }
         }
         if (r < 0)
@@ -159,24 +163,17 @@ static int call_get_os_release(sd_bus *bus, const char *method, const char *name
         if (r < 0)
                 return bus_log_parse_error(r);
 
+        r = 0;
+
         va_start(ap, query);
-        for (count = 0; count < awaited_args; count++) {
-                char *val, **out;
-
-                out = va_arg(ap, char **);
-                assert(out);
-                if (query_res[count]) {
-                        val = strdup(query_res[count]);
-                        if (!val) {
-                                va_end(ap);
-                                return -ENOMEM;
-                        }
-                        *out = val;
-                }
+        FOREACH_ARRAY(i, res, n_fields) {
+                r = strdup_to(va_arg(ap, char**), *i);
+                if (r < 0)
+                        break;
         }
         va_end(ap);
 
-        return 0;
+        return r;
 }
 
 static int call_get_addresses(
@@ -205,12 +202,12 @@ static int call_get_addresses(
         addresses = strdup(prefix);
         if (!addresses)
                 return log_oom();
-        prefix = "";
 
         r = sd_bus_message_enter_container(reply, 'a', "(iay)");
         if (r < 0)
                 return bus_log_parse_error(r);
 
+        prefix = "";
         while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
                 int family;
                 const void *a;
index 7ee0961fa6a00dae1694aa6ccfc2763c27d2751e..117789c6e6eb62543978a936045abcd076105847 100644 (file)
@@ -93,7 +93,7 @@ JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
 STATIC_DESTRUCTOR_REGISTER(arg_drop_in, freep);
 
 static int varlink_connect_networkd(Varlink **ret_varlink) {
-        _cleanup_(varlink_unrefp) Varlink *vl = NULL;
+        _cleanup_(varlink_flush_close_unrefp) Varlink *vl = NULL;
         JsonVariant *reply;
         uint64_t id;
         int r;
@@ -102,6 +102,12 @@ static int varlink_connect_networkd(Varlink **ret_varlink) {
         if (r < 0)
                 return log_error_errno(r, "Failed to connect to network service /run/systemd/netif/io.systemd.Network: %m");
 
+        (void) varlink_set_description(vl, "varlink-network");
+
+        r = varlink_set_allow_fd_passing_output(vl, true);
+        if (r < 0)
+                return log_error_errno(r, "Failed to allow passing file descriptor through varlink: %m");
+
         r = varlink_call_and_log(vl, "io.systemd.Network.GetNamespaceId", /* parameters= */ NULL, &reply);
         if (r < 0)
                 return r;
@@ -2427,7 +2433,7 @@ static int link_status(int argc, char *argv[], void *userdata) {
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
-        _cleanup_(varlink_unrefp) Varlink *vl = NULL;
+        _cleanup_(varlink_flush_close_unrefp) Varlink *vl = NULL;
         _cleanup_(link_info_array_freep) LinkInfo *links = NULL;
         int r, c;
 
@@ -2589,7 +2595,7 @@ static int dump_lldp_neighbors_json(JsonVariant *reply, char * const *patterns)
 }
 
 static int link_lldp_status(int argc, char *argv[], void *userdata) {
-        _cleanup_(varlink_unrefp) Varlink *vl = NULL;
+        _cleanup_(varlink_flush_close_unrefp) Varlink *vl = NULL;
         _cleanup_(table_unrefp) Table *table = NULL;
         JsonVariant *reply;
         uint64_t all = 0;
@@ -2930,7 +2936,7 @@ static int verb_reconfigure(int argc, char *argv[], void *userdata) {
 }
 
 static int verb_persistent_storage(int argc, char *argv[], void *userdata) {
-        _cleanup_(varlink_unrefp) Varlink *vl = NULL;
+        _cleanup_(varlink_flush_close_unrefp) Varlink *vl = NULL;
         bool ready;
         int r;
 
@@ -2943,6 +2949,20 @@ static int verb_persistent_storage(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
+        if (ready) {
+                _cleanup_close_ int fd = -EBADF;
+
+                fd = open("/var/lib/systemd/network/", O_CLOEXEC | O_DIRECTORY);
+                if (fd < 0)
+                        return log_error_errno(errno, "Failed to open /var/lib/systemd/network/: %m");
+
+                r = varlink_push_fd(vl, fd);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to push file descriptor of /var/lib/systemd/network/ into varlink: %m");
+
+                TAKE_FD(fd);
+        }
+
         return varlink_callb_and_log(vl, "io.systemd.Network.SetPersistentStorage", /* reply = */ NULL,
                                      JSON_BUILD_OBJECT(JSON_BUILD_PAIR_BOOLEAN("Ready", ready)));
 }
index 49a43753c5e7bdffa1050573fc795cd60b9e5b4f..38cdadcf61bb1a93b06160f8c4d1e0fbcfaf0c52 100644 (file)
@@ -613,12 +613,12 @@ int address_dup(const Address *src, Address **ret) {
         dest->nft_set_context.n_sets = 0;
 
         if (src->family == AF_INET) {
-                r = strdup_or_null(src->label, &dest->label);
+                r = strdup_to(&dest->label, src->label);
                 if (r < 0)
                         return r;
         }
 
-        r = strdup_or_null(src->netlabel, &dest->netlabel);
+        r = strdup_to(&dest->netlabel, src->netlabel);
         if (r < 0)
                 return r;
 
@@ -1415,43 +1415,6 @@ void link_foreignize_addresses(Link *link) {
                 address->source = NETWORK_CONFIG_SOURCE_FOREIGN;
 }
 
-static int address_acquire(Link *link, const Address *original, Address **ret) {
-        _cleanup_(address_unrefp) Address *na = NULL;
-        union in_addr_union in_addr;
-        int r;
-
-        assert(link);
-        assert(original);
-        assert(ret);
-
-        /* Something useful was configured? just use it */
-        if (in_addr_is_set(original->family, &original->in_addr))
-                return address_dup(original, ret);
-
-        /* The address is configured to be 0.0.0.0 or [::] by the user?
-         * Then let's acquire something more useful from the pool. */
-        r = address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr);
-        if (r < 0)
-                return r;
-        if (r == 0)
-                return -EBUSY;
-
-        /* Pick first address in range for ourselves. */
-        if (original->family == AF_INET)
-                in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1);
-        else if (original->family == AF_INET6)
-                in_addr.in6.s6_addr[15] |= 1;
-
-        r = address_dup(original, &na);
-        if (r < 0)
-                return r;
-
-        na->in_addr = in_addr;
-
-        *ret = TAKE_PTR(na);
-        return 0;
-}
-
 int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg) {
         int r;
 
@@ -1524,21 +1487,67 @@ static int address_configure(const Address *address, const struct ifa_cacheinfo
         return request_call_netlink_async(link->manager->rtnl, m, req);
 }
 
-static bool address_is_ready_to_configure(Link *link, const Address *address) {
+static int address_acquire(Link *link, const Address *address, union in_addr_union *ret) {
+        union in_addr_union a;
+        int r;
+
         assert(link);
         assert(address);
+        assert(ret);
 
-        if (!link_is_ready_to_configure(link, false))
-                return false;
+        r = address_pool_acquire(link->manager, address->family, address->prefixlen, &a);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return -EBUSY;
 
-        if (!ipv4acd_bound(link, address))
-                return false;
+        /* Pick first address in range for ourselves. */
+        if (address->family == AF_INET)
+                a.in.s_addr |= htobe32(1);
+        else if (address->family == AF_INET6)
+                a.in6.s6_addr[15] |= 1;
+        else
+                assert_not_reached();
 
-        /* Refuse adding more than the limit */
-        if (set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX)
-                return false;
+        *ret = a;
+        return 0;
+}
 
-        return true;
+static int address_requeue_request(Request *req, Link *link, const Address *address) {
+        int r;
+
+        assert(req);
+        assert(link);
+        assert(link->manager);
+        assert(link->network);
+        assert(address);
+
+        /* Something useful was configured? just use it */
+        if (in_addr_is_set(address->family, &address->in_addr))
+                return 0;
+
+        /* The address is configured to be 0.0.0.0 or [::] by the user?
+         * Then let's acquire something more useful. */
+        union in_addr_union a;
+        r = address_acquire(link, address, &a);
+        if (r < 0)
+                return r;
+
+        _cleanup_(address_unrefp) Address *tmp = NULL;
+        r = address_dup(address, &tmp);
+        if (r < 0)
+                return r;
+
+        tmp->in_addr = a;
+
+        r = link_requeue_request(link, req, tmp, NULL);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return -EEXIST; /* Already queued?? Strange... */
+
+        TAKE_PTR(tmp);
+        return 1; /* A new request is queued. it is not necessary to process this request anymore. */
 }
 
 static int address_process_request(Request *req, Link *link, Address *address) {
@@ -1550,7 +1559,26 @@ static int address_process_request(Request *req, Link *link, Address *address) {
         assert(link);
         assert(address);
 
-        if (!address_is_ready_to_configure(link, address))
+        if (!link_is_ready_to_configure(link, false))
+                return 0;
+
+        /* Refuse adding more than the limit */
+        if (set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX)
+                return 0;
+
+        r = address_requeue_request(req, link, address);
+        if (r == -EBUSY)
+                return 0;
+        if (r != 0)
+                return r;
+
+        address_set_broadcast(address, link);
+
+        r = ipv4acd_configure(link, address);
+        if (r < 0)
+                return r;
+
+        if (!ipv4acd_bound(link, address))
                 return 0;
 
         address_set_cinfo(link->manager, address, &c);
@@ -1595,19 +1623,14 @@ int link_request_address(
                 /* The requested address is outdated. Let's ignore the request. */
                 return 0;
 
-        if (address_get(link, address, &existing) < 0) {
-                if (address_get_request(link, address, NULL) >= 0)
-                        return 0; /* already requested, skipping. */
+        if (address_get_request(link, address, NULL) >= 0)
+                return 0; /* already requested, skipping. */
 
-                r = address_acquire(link, address, &tmp);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "Failed to acquire an address from pool: %m");
-
-        } else {
-                r = address_dup(address, &tmp);
-                if (r < 0)
-                        return log_oom();
+        r = address_dup(address, &tmp);
+        if (r < 0)
+                return log_oom();
 
+        if (address_get(link, address, &existing) >= 0) {
                 /* Copy already assigned address when it is requested as a null address. */
                 if (address_is_static_null(address))
                         tmp->in_addr = existing->in_addr;
@@ -1616,12 +1639,6 @@ int link_request_address(
                 tmp->state = existing->state;
         }
 
-        address_set_broadcast(tmp, link);
-
-        r = ipv4acd_configure(link, tmp);
-        if (r < 0)
-                return r;
-
         log_address_debug(tmp, "Requesting", link);
         r = link_queue_request_safe(link, REQUEST_TYPE_ADDRESS,
                                     tmp,
index 57019400e6a28effc4c0021297194be236c3bc07..a1869a855998b2c5666c4626a7eba1f73eb3e0df 100644 (file)
@@ -144,7 +144,7 @@ int network_adjust_dhcp_server(Network *network, Set **addresses) {
         return 0;
 }
 
-static int link_start_dhcp4_server(Link *link) {
+int link_start_dhcp4_server(Link *link) {
         int r;
 
         assert(link);
@@ -156,12 +156,25 @@ static int link_start_dhcp4_server(Link *link) {
         if (!link_has_carrier(link))
                 return 0;
 
+        if (sd_dhcp_server_is_running(link->dhcp_server))
+                return 0; /* already started. */
+
         /* TODO: Maybe, also check the system time is synced. If the system does not have RTC battery, then
          * the realtime clock in not usable in the early boot stage, and all saved leases may be wrongly
          * handled as expired and dropped. */
-        if (!sd_dhcp_server_is_in_relay_mode(link->dhcp_server) &&
-            !link->manager->persistent_storage_is_ready)
-                return 0;
+        if (!sd_dhcp_server_is_in_relay_mode(link->dhcp_server)) {
+
+                if (link->manager->persistent_storage_fd < 0)
+                        return 0; /* persistent storage is not ready. */
+
+                _cleanup_free_ char *lease_file = path_join("dhcp-server-lease", link->ifname);
+                if (!lease_file)
+                        return -ENOMEM;
+
+                r = sd_dhcp_server_set_lease_file(link->dhcp_server, link->manager->persistent_storage_fd, lease_file);
+                if (r < 0)
+                        return r;
+        }
 
         r = sd_dhcp_server_start(link->dhcp_server);
         if (r < 0)
@@ -183,13 +196,18 @@ void manager_toggle_dhcp4_server_state(Manager *manager, bool start) {
                 if (sd_dhcp_server_is_in_relay_mode(link->dhcp_server))
                         continue;
 
-                if (start)
-                        r = link_start_dhcp4_server(link);
-                else
-                        r = sd_dhcp_server_stop(link->dhcp_server);
+                /* Even if 'start' is true, first we need to stop the server. Otherwise, we cannot (re)set
+                 * the lease file in link_start_dhcp4_server(). */
+                r = sd_dhcp_server_stop(link->dhcp_server);
                 if (r < 0)
-                        log_link_debug_errno(link, r, "Failed to %s DHCP server, ignoring: %m",
-                                             start ? "start" : "stop");
+                        log_link_debug_errno(link, r, "Failed to stop DHCP server, ignoring: %m");
+
+                if (!start)
+                        continue;
+
+                r = link_start_dhcp4_server(link);
+                if (r < 0)
+                        log_link_debug_errno(link, r, "Failed to start DHCP server, ignoring: %m");
         }
 }
 
@@ -572,16 +590,6 @@ static int dhcp4_server_configure(Link *link) {
                         return log_link_error_errno(link, r, "Failed to set DHCPv4 static lease for DHCP server: %m");
         }
 
-        if (!sd_dhcp_server_is_in_relay_mode(link->dhcp_server)) {
-                _cleanup_free_ char *lease_file = path_join("/var/lib/systemd/network/dhcp-server-lease/", link->ifname);
-                if (!lease_file)
-                        return log_oom();
-
-                r = sd_dhcp_server_set_lease_file(link->dhcp_server, lease_file);
-                if (r < 0)
-                        log_link_warning_errno(link, r, "Failed to load DHCPv4 server leases, ignoring: %m");
-        }
-
         r = link_start_dhcp4_server(link);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not start DHCPv4 server instance: %m");
index b845a6d1c777f41467dc909eb512e161277ee71c..dbc7d95cadba470a3f94f01f8ba99f19c5e607a5 100644 (file)
@@ -12,6 +12,7 @@ int network_adjust_dhcp_server(Network *network, Set **addresses);
 
 int link_request_dhcp_server(Link *link);
 
+int link_start_dhcp4_server(Link *link);
 void manager_toggle_dhcp4_server_state(Manager *manager, bool start);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_agent_suboption);
index 650e94c31378626b3bb38dcfc8fd78bb1d5a1a91..3e8aa9e37aaadedf31dd6799558a7b8bfd1cc513 100644 (file)
@@ -713,11 +713,9 @@ static int link_acquire_dynamic_ipv4_conf(Link *link) {
                 log_link_debug(link, "Acquiring IPv4 link-local address.");
         }
 
-        if (link->dhcp_server) {
-                r = sd_dhcp_server_start(link->dhcp_server);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "Could not start DHCP server: %m");
-        }
+        r = link_start_dhcp4_server(link);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Could not start DHCP server: %m");
 
         r = ipv4acd_start(link);
         if (r < 0)
index c86505b039d53590929fd53466044955d9b38f81..31aebfc389782ad78eceeb084d9c53b5134d38d0 100644 (file)
@@ -3,7 +3,7 @@
 #include <unistd.h>
 
 #include "bus-polkit.h"
-#include "fs-util.h"
+#include "fd-util.h"
 #include "lldp-rx-internal.h"
 #include "networkd-dhcp-server.h"
 #include "networkd-manager-varlink.h"
@@ -185,13 +185,42 @@ static int vl_method_set_persistent_storage(Varlink *vlink, JsonVariant *paramet
                 return r;
 
         if (ready) {
-                r = path_is_read_only_fs("/var/lib/systemd/network/");
+                struct stat st, st_prev;
+                int fd;
+
+                fd = varlink_peek_fd(vlink, 0);
+                if (fd < 0)
+                        return log_warning_errno(fd, "Failed to peek file descriptor of the persistent storage: %m");
+
+                r = fd_verify_safe_flags_full(fd, O_DIRECTORY);
+                if (r == -EREMOTEIO)
+                        return log_warning_errno(r, "Passed persistent storage fd has unexpected flags, refusing.");
+                if (r < 0)
+                        return log_warning_errno(r, "Failed to verify flags of passed persistent storage fd: %m");
+
+                r = fd_is_read_only_fs(fd);
                 if (r < 0)
-                        return log_warning_errno(r, "Failed to check if /var/lib/systemd/network/ is writable: %m");
+                        return log_warning_errno(r, "Failed to check if the persistent storage is writable: %m");
                 if (r > 0) {
-                        log_warning("The directory /var/lib/systemd/network/ is read-only.");
+                        log_warning("The persistent storage is on read-only filesystem.");
                         return varlink_error(vlink, "io.systemd.Network.StorageReadOnly", NULL);
                 }
+
+                if (fstat(fd, &st) < 0)
+                        return log_warning_errno(r, "Failed to stat the passed persistent storage fd: %m");
+
+                r = stat_verify_directory(&st);
+                if (r < 0)
+                        return log_warning_errno(r, "The passed persistent storage fd is not a directory, refusing: %m");
+
+                if (manager->persistent_storage_fd >= 0 &&
+                    fstat(manager->persistent_storage_fd, &st_prev) >= 0 &&
+                    stat_inode_same(&st, &st_prev))
+                        return varlink_reply(vlink, NULL);
+
+        } else {
+                if (manager->persistent_storage_fd < 0)
+                        return varlink_reply(vlink, NULL);
         }
 
         r = varlink_verify_polkit_async(
@@ -203,22 +232,34 @@ static int vl_method_set_persistent_storage(Varlink *vlink, JsonVariant *paramet
         if (r <= 0)
                 return r;
 
-        manager->persistent_storage_is_ready = ready;
-
         if (ready) {
-                r = touch("/run/systemd/netif/persistent-storage-ready");
-                if (r < 0)
-                        log_debug_errno(r, "Failed to create /run/systemd/netif/persistent-storage-ready, ignoring: %m");
-        } else {
-                if (unlink("/run/systemd/netif/persistent-storage-ready") < 0 && errno != ENOENT)
-                        log_debug_errno(errno, "Failed to remove /run/systemd/netif/persistent-storage-ready, ignoring: %m");
-        }
+                _cleanup_close_ int fd = -EBADF;
+
+                fd = varlink_take_fd(vlink, 0);
+                if (fd < 0)
+                        return log_warning_errno(fd, "Failed to take file descriptor of the persistent storage: %m");
+
+                close_and_replace(manager->persistent_storage_fd, fd);
+        } else
+                manager->persistent_storage_fd = safe_close(manager->persistent_storage_fd);
 
         manager_toggle_dhcp4_server_state(manager, ready);
 
         return varlink_reply(vlink, NULL);
 }
 
+static int on_connect(VarlinkServer *s, Varlink *vlink, void *userdata) {
+        int r;
+
+        assert(vlink);
+
+        r = varlink_set_allow_fd_passing_input(vlink, true);
+        if (r < 0)
+                return log_warning_errno(r, "Failed to allow receiving file descriptor through varlink: %m");
+
+        return 0;
+}
+
 int manager_connect_varlink(Manager *m) {
         _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
         int r;
@@ -234,6 +275,8 @@ int manager_connect_varlink(Manager *m) {
 
         varlink_server_set_userdata(s, m);
 
+        (void) varlink_server_set_description(s, "varlink-api-network");
+
         r = varlink_server_add_interface(s, &vl_interface_io_systemd_Network);
         if (r < 0)
                 return log_error_errno(r, "Failed to add Network interface to varlink server: %m");
@@ -255,6 +298,10 @@ int manager_connect_varlink(Manager *m) {
         if (r < 0)
                 return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
 
+        r = varlink_server_bind_connect(s, on_connect);
+        if (r < 0)
+                return log_error_errno(r, "Failed to set on-connect callback for varlink: %m");
+
         m->varlink_server = TAKE_PTR(s);
         return 0;
 }
index 2545521b991b6ca5879f7a195d8a3f62e43d11bb..5c50b3c98a26321e60e03719302fa31ffe765803 100644 (file)
@@ -23,6 +23,7 @@
 #include "device-private.h"
 #include "device-util.h"
 #include "dns-domain.h"
+#include "env-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "firewall-util.h"
@@ -557,27 +558,27 @@ int manager_setup(Manager *m) {
         return 0;
 }
 
-static bool persistent_storage_is_ready(void) {
+static int persistent_storage_open(void) {
+        _cleanup_close_ int fd = -EBADF;
         int r;
 
-        if (access("/run/systemd/netif/persistent-storage-ready", F_OK) < 0) {
-                if (errno != ENOENT)
-                        log_debug_errno(errno, "Failed to check if /run/systemd/netif/persistent-storage-ready exists, assuming not: %m");
-                return false;
-        }
+        r = getenv_bool("SYSTEMD_NETWORK_PERSISTENT_STORAGE_READY");
+        if (r < 0 && r != -ENXIO)
+                return log_debug_errno(r, "Failed to parse $SYSTEMD_NETWORK_PERSISTENT_STORAGE_READY environment variable, ignoring: %m");
+        if (r <= 0)
+                return -EBADF;
 
-        r = path_is_read_only_fs("/var/lib/systemd/network/");
-        if (r == 0)
-                return true;
-        if (r < 0)
-                log_debug_errno(r, "Failed to check if /var/lib/systemd/network/ is writable: %m");
-        else
-                log_debug("The directory /var/lib/systemd/network/ is read-only.");
+        fd = open("/var/lib/systemd/network/", O_CLOEXEC | O_DIRECTORY | O_PATH);
+        if (fd < 0)
+                return log_debug_errno(errno, "Failed to open /var/lib/systemd/network/, ignoring: %m");
 
-        if (unlink("/run/systemd/netif/persistent-storage-ready") < 0 && errno != ENOENT)
-                log_debug_errno(errno, "Failed to remove /run/systemd/netif/persistent-storage-ready, ignoring: %m");
+        r = fd_is_read_only_fs(fd);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to check if /var/lib/systemd/network/ is writable: %m");
+        if (r > 0)
+                return log_debug_errno(SYNTHETIC_ERRNO(EROFS), "The directory /var/lib/systemd/network/ is on read-only filesystem.");
 
-        return false;
+        return TAKE_FD(fd);
 }
 
 int manager_new(Manager **ret, bool test_mode) {
@@ -591,13 +592,13 @@ int manager_new(Manager **ret, bool test_mode) {
                 .keep_configuration = _KEEP_CONFIGURATION_INVALID,
                 .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
                 .test_mode = test_mode,
-                .persistent_storage_is_ready = persistent_storage_is_ready(),
                 .speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL,
                 .online_state = _LINK_ONLINE_STATE_INVALID,
                 .manage_foreign_routes = true,
                 .manage_foreign_rules = true,
                 .manage_foreign_nexthops = true,
                 .ethtool_fd = -EBADF,
+                .persistent_storage_fd = persistent_storage_open(),
                 .dhcp_duid.type = DUID_TYPE_EN,
                 .dhcp6_duid.type = DUID_TYPE_EN,
                 .duid_product_uuid.type = DUID_TYPE_UUID,
@@ -672,6 +673,7 @@ Manager* manager_free(Manager *m) {
         free(m->dynamic_hostname);
 
         safe_close(m->ethtool_fd);
+        safe_close(m->persistent_storage_fd);
 
         m->fw_ctx = fw_ctx_free(m->fw_ctx);
 
index 320b859bfd839526a53e5aeed0f165f7a02c79ab..fd9ab341c83545af7d0253dc0f901e5fc72ca1d7 100644 (file)
@@ -30,6 +30,7 @@ struct Manager {
         sd_device_monitor *device_monitor;
         Hashmap *polkit_registry;
         int ethtool_fd;
+        int persistent_storage_fd;
 
         KeepConfiguration keep_configuration;
         IPv6PrivacyExtensions ipv6_privacy_extensions;
@@ -41,7 +42,6 @@ struct Manager {
         bool manage_foreign_routes;
         bool manage_foreign_rules;
         bool manage_foreign_nexthops;
-        bool persistent_storage_is_ready;
 
         Set *dirty_links;
         Set *new_wlan_ifindices;
index f1dd6b44d251cdc71897ab014900e04593b28138..98c629f161dc6bf556f648d18cfd889cef53d29d 100644 (file)
@@ -216,6 +216,23 @@ int link_queue_request_full(
                            process, counter, netlink_handler, ret);
 }
 
+int link_requeue_request(Link *link, Request *req, void *userdata, Request **ret) {
+        assert(link);
+        assert(req);
+
+        return link_queue_request_full(
+                        link,
+                        req->type,
+                        userdata,
+                        req->free_func,
+                        req->hash_func,
+                        req->compare_func,
+                        req->process,
+                        req->counter,
+                        req->netlink_handler,
+                        ret);
+}
+
 int manager_process_requests(Manager *manager) {
         Request *req;
         int r;
index bdedc775377b9c56ed1df117cc01032757fe4642..e35cd73efd944def8120bce462d904cef36e557a 100644 (file)
@@ -107,6 +107,8 @@ int link_queue_request_full(
                 request_netlink_handler_t netlink_handler,
                 Request **ret);
 
+int link_requeue_request(Link *link, Request *req, void *userdata, Request **ret);
+
 static inline int link_queue_request(
                 Link *link,
                 RequestType type,
index 1bae89393467a3bc339fd9cf7754d074d98aa7ef..31a2bdea24c112124964f51d0c9e53abc2c36133 100644 (file)
@@ -39,7 +39,7 @@ int route_metric_copy(const RouteMetric *src, RouteMetric *dest) {
         } else
                 dest->metrics_set = NULL;
 
-        return strdup_or_null(src->tcp_congestion_control_algo, &dest->tcp_congestion_control_algo);
+        return strdup_to(&dest->tcp_congestion_control_algo, src->tcp_congestion_control_algo);
 }
 
 void route_metric_hash_func(const RouteMetric *metric, struct siphash *state) {
index 8ba7505987aeec42c406d258bfd627c536f7588d..11215c36c717f063bedb643f4b2241c63fd0a6e3 100644 (file)
@@ -218,7 +218,7 @@ static int route_nexthop_copy(const RouteNextHop *src, RouteNextHop *dest) {
         /* unset pointer copied in the above. */
         dest->ifname = NULL;
 
-        return strdup_or_null(src->ifindex > 0 ? NULL : src->ifname, &dest->ifname);
+        return strdup_to(&dest->ifname, src->ifindex > 0 ? NULL : src->ifname);
 }
 
 static int route_nexthop_dup(const RouteNextHop *src, RouteNextHop **ret) {
index 3c5de98e7c96181439a0b640855f4d0750302890..efe378a457289beac0309786376b44fa90eedaf1 100644 (file)
@@ -780,16 +780,7 @@ static int route_requeue_request(Request *req, Link *link, const Route *route) {
         request_detach(req);
 
         /* Request the route with the adjusted Route object combined with the same other parameters. */
-        r = link_queue_request_full(link,
-                                    req->type,
-                                    tmp,
-                                    req->free_func,
-                                    req->hash_func,
-                                    req->compare_func,
-                                    req->process,
-                                    req->counter,
-                                    req->netlink_handler,
-                                    NULL);
+        r = link_requeue_request(link, req, tmp, NULL);
         if (r < 0)
                 return r;
         if (r == 0)
index c415d3cec1416a7eb53b8e547072da18acac6194..3d0a9a73e3d68d2f59a5d587f61587f2cc571e9d 100644 (file)
@@ -3958,7 +3958,7 @@ static int outer_child(
 
         if (dissected_image) {
                 /* Now we know the uid shift, let's now mount everything else that might be in the image. */
-                r = dissected_image_mount(
+                r = dissected_image_mount_and_warn(
                                 dissected_image,
                                 directory,
                                 arg_uid_shift,
@@ -3967,10 +3967,8 @@ static int outer_child(
                                 determine_dissect_image_flags()|
                                 DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY|
                                 (idmap ? DISSECT_IMAGE_MOUNT_IDMAPPED : 0));
-                if (r == -EUCLEAN)
-                        return log_error_errno(r, "File system check for image failed: %m");
                 if (r < 0)
-                        return log_error_errno(r, "Failed to mount image file system: %m");
+                        return r;
         }
 
         if (arg_unified_cgroup_hierarchy == CGROUP_UNIFIED_UNKNOWN) {
@@ -4408,6 +4406,17 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
         if (!tags)
                 return log_oom();
 
+        if (DEBUG_LOGGING) {
+                _cleanup_free_ char *joined = strv_join(tags, " ");
+
+                if (joined) {
+                        _cleanup_free_ char *j = cescape(joined);
+                        free_and_replace(joined, j);
+                }
+
+                log_debug("Got sd_notify() message: %s", strnull(joined));
+        }
+
         if (strv_contains(tags, "READY=1")) {
                 r = sd_notify(false, "READY=1\n");
                 if (r < 0)
index 6e6678c33d990b8113bda61299848eb8436ec8cd..69d103e71f04c77921ebb7f48ca160a611bb64c0 100644 (file)
@@ -321,17 +321,16 @@ int oomd_kill_by_pgscan_rate(Hashmap *h, const char *prefix, bool dry_run, char
                 if (r == -ENOMEM)
                         return r; /* Treat oom as a hard error */
                 if (r < 0) {
-                        if (ret == 0)
-                                ret = r;
+                        RET_GATHER(ret, r);
                         continue; /* Try to find something else to kill */
                 }
 
                 dump_until = MAX(dump_until, i + 1);
-                char *selected = strdup(sorted[i]->path);
-                if (!selected)
-                        return -ENOMEM;
-                *ret_selected = selected;
+
                 ret = r;
+                r = strdup_to(ret_selected, sorted[i]->path);
+                if (r < 0)
+                        return r;
                 break;
         }
 
@@ -365,17 +364,16 @@ int oomd_kill_by_swap_usage(Hashmap *h, uint64_t threshold_usage, bool dry_run,
                 if (r == -ENOMEM)
                         return r; /* Treat oom as a hard error */
                 if (r < 0) {
-                        if (ret == 0)
-                                ret = r;
+                        RET_GATHER(ret, r);
                         continue; /* Try to find something else to kill */
                 }
 
                 dump_until = MAX(dump_until, i + 1);
-                char *selected = strdup(sorted[i]->path);
-                if (!selected)
-                        return -ENOMEM;
-                *ret_selected = selected;
+
                 ret = r;
+                r = strdup_to(ret_selected, sorted[i]->path);
+                if (r < 0)
+                        return r;
                 break;
         }
 
@@ -442,9 +440,9 @@ int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret) {
                         return log_debug_errno(r, "Error converting pgscan value to uint64_t: %m");
         }
 
-        ctx->path = strdup(empty_to_root(path));
-        if (!ctx->path)
-                return -ENOMEM;
+        r = strdup_to(&ctx->path, empty_to_root(path));
+        if (r < 0)
+                return r;
 
         *ret = TAKE_PTR(ctx);
         return 0;
index adf1f0e6965520ba3ebb4fa0ca93c224e39ba0d7..ddb7fcb046d7ef0cdf812ba0e993974fbafff365 100644 (file)
@@ -3329,8 +3329,8 @@ static int context_dump(Context *context, bool late) {
         if (r < 0)
                 return r;
 
-        /* Make sure we only write the partition bar once, even if we're writing the partition table twice to
-         * communicate roothashes. */
+        /* Only write the partition bar once, even if we're writing the partition table twice to communicate
+         * roothashes. */
         if (FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF) && !late) {
                 putc('\n', stdout);
 
@@ -4239,7 +4239,7 @@ static int partition_format_verity_hash(
         if (PARTITION_EXISTS(p)) /* Never format existing partitions */
                 return 0;
 
-        /* Minimized partitions will use the copy blocks logic so let's make sure to skip those here. */
+        /* Minimized partitions will use the copy blocks logic so skip those here. */
         if (p->copy_blocks_fd >= 0)
                 return 0;
 
@@ -4986,7 +4986,7 @@ static int context_mkfs(Context *context) {
                 if (!p->format)
                         continue;
 
-                /* Minimized partitions will use the copy blocks logic so let's make sure to skip those here. */
+                /* Minimized partitions will use the copy blocks logic so skip those here. */
                 if (p->copy_blocks_fd >= 0)
                         continue;
 
@@ -4997,7 +4997,7 @@ static int context_mkfs(Context *context) {
                 assert(p->new_size != UINT64_MAX);
                 assert(p->new_size >= (p->encrypt != ENCRYPT_OFF ? LUKS2_METADATA_KEEP_FREE : 0));
 
-                /* If we're doing encryption, we make sure we keep free space at the end which is required
+                /* If we're doing encryption, keep free space at the end which is required
                  * for cryptsetup's offline encryption. */
                 r = partition_target_prepare(context, p,
                                              p->new_size - (p->encrypt != ENCRYPT_OFF ? LUKS2_METADATA_KEEP_FREE : 0),
@@ -5046,8 +5046,8 @@ static int context_mkfs(Context *context) {
                         return r;
 
                 /* The mkfs binary we invoked might have removed our temporary file when we're not operating
-                 * on a loop device, so let's make sure we open the file again to make sure our file
-                 * descriptor points to any potential new file. */
+                 * on a loop device, so open the file again to make sure our file descriptor points to actual
+                 * new file. */
 
                 if (t->fd >= 0 && t->path && !t->loop) {
                         safe_close(t->fd);
index a003ea03520166aa496ad05f6788ea7e437c9d8c..a3bec83f0dddf81c0ed8a8f558cbf05c2561d23c 100644 (file)
@@ -1473,6 +1473,7 @@ static void log_portable_verb(
                 const char *verb,
                 const char *message_id,
                 const char *image_path,
+                const char *profile,
                 OrderedHashmap *extension_images,
                 char **extension_image_paths,
                 PortableFlags flags) {
@@ -1531,12 +1532,14 @@ static void log_portable_verb(
         LOG_CONTEXT_PUSH_STRV(extension_base_names);
 
         log_struct(LOG_INFO,
-                   LOG_MESSAGE("Successfully %s%s '%s%s%s'",
+                   LOG_MESSAGE("Successfully %s%s '%s%s%s%s%s'",
                                verb,
                                FLAGS_SET(flags, PORTABLE_RUNTIME) ? " ephemeral" : "",
                                image_path,
                                isempty(extensions_joined) ? "" : "' and its extension(s) '",
-                               strempty(extensions_joined)),
+                               strempty(extensions_joined),
+                               isempty(profile) ? "" : "' using profile '",
+                               strempty(profile)),
                    message_id,
                    "PORTABLE_ROOT=%s", strna(root_base_name));
 }
@@ -1653,6 +1656,7 @@ int portable_attach(
                         "attached",
                         "MESSAGE_ID=" SD_MESSAGE_PORTABLE_ATTACHED_STR,
                         image->path,
+                        profile,
                         extension_images,
                         /* extension_image_paths= */ NULL,
                         flags);
@@ -1974,6 +1978,7 @@ int portable_detach(
                         "detached",
                         "MESSAGE_ID=" SD_MESSAGE_PORTABLE_DETACHED_STR,
                         name_or_path,
+                        /* profile= */ NULL,
                         /* extension_images= */ NULL,
                         extension_image_paths,
                         flags);
index db5e4febe0a9b8954ede8599d3b19707454a44d9..0f67e4432f2160dfc337518d920b3bc84e4626a6 100644 (file)
@@ -1251,7 +1251,8 @@ static int help(int argc, char *argv[], void *userdata) {
                "  -M --machine=CONTAINER      Operate on local container\n"
                "  -q --quiet                  Suppress informational messages\n"
                "  -p --profile=PROFILE        Pick security profile for portable service\n"
-               "     --copy=copy|auto|symlink Prefer copying or symlinks if possible\n"
+               "     --copy=copy|auto|symlink|mixed\n"
+               "                              Pick copying or symlinking of resources\n"
                "     --runtime                Attach portable service until next reboot only\n"
                "     --no-reload              Don't reload the system and service manager\n"
                "     --cat                    When inspecting include unit and os-release file\n"
index b648c3e520342d3556ca27d58896adb8b90c16f7..504da9ebca31ed0eb655ee939be5d1ace8e99156 100644 (file)
@@ -299,6 +299,37 @@ int config_parse_dnssd_service_type(
         return 0;
 }
 
+int config_parse_dnssd_service_subtype(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        DnssdService *s = ASSERT_PTR(userdata);
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                s->subtype = mfree(s->subtype);
+                return 0;
+        }
+
+        if (!dns_subtype_name_is_valid(rvalue)) {
+                log_syntax(unit, LOG_WARNING, filename, line, 0, "Service subtype is invalid. Ignoring.");
+                return 0;
+        }
+
+        return free_and_strdup_warn(&s->subtype, rvalue);
+}
+
 int config_parse_dnssd_txt(
                 const char *unit,
                 const char *filename,
index 07ce2591a9ca2fdb110602f8e9bddcac474cb60e..ca768bb2d9fadfd4ae79e769e6c2a610bff5fa70 100644 (file)
@@ -17,6 +17,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dns_servers);
 CONFIG_PARSER_PROTOTYPE(config_parse_search_domains);
 CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_name);
+CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_subtype);
 CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_type);
 CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_txt);
 CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_extra);
index 801bbe8007e136d18684bd459525b813f11473f7..14adb904bdfed6a90d24128d22117b3d2d2945ad 100644 (file)
@@ -57,6 +57,21 @@ static void dns_query_candidate_stop(DnsQueryCandidate *c) {
         }
 }
 
+static void dns_query_candidate_abandon(DnsQueryCandidate *c) {
+        DnsTransaction *t;
+
+        assert(c);
+
+        /* Abandon all the DnsTransactions attached to this query */
+
+        while ((t = set_steal_first(c->transactions))) {
+                t->wait_for_answer = true;
+                set_remove(t->notify_query_candidates, c);
+                set_remove(t->notify_query_candidates_done, c);
+                dns_transaction_gc(t);
+        }
+}
+
 static DnsQueryCandidate* dns_query_candidate_unlink(DnsQueryCandidate *c) {
         assert(c);
 
@@ -354,6 +369,16 @@ static void dns_query_stop(DnsQuery *q) {
                 dns_query_candidate_stop(c);
 }
 
+static void dns_query_abandon(DnsQuery *q) {
+        assert(q);
+
+        /* Thankfully transactions have their own timeouts */
+        event_source_disable(q->timeout_event_source);
+
+        LIST_FOREACH(candidates_by_query, c, q->candidates)
+                dns_query_candidate_abandon(c);
+}
+
 static void dns_query_unlink_candidates(DnsQuery *q) {
         assert(q);
 
@@ -591,7 +616,7 @@ void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
 
         (void) manager_monitor_send(q->manager, q);
 
-        dns_query_stop(q);
+        dns_query_abandon(q);
         if (q->complete)
                 q->complete(q);
 }
index ca30508ff4c456611e87a0c3f42d37cda4c46313..2739bed41a3e56515a9e8971c5ddee492f9a9829 100644 (file)
@@ -182,6 +182,23 @@ bool dns_resource_key_is_dnssd_ptr(const DnsResourceKey *key) {
                 dns_name_endswith(dns_resource_key_name(key), "_udp.local");
 }
 
+bool dns_resource_key_is_dnssd_two_label_ptr(const DnsResourceKey *key) {
+        assert(key);
+
+        /* Check if this is a PTR resource key used in Service Instance
+         * Enumeration as described in RFC6763 § 4.1, excluding selective
+         * service names described in RFC6763 § 7.1. */
+
+        if (key->type != DNS_TYPE_PTR)
+                return false;
+
+        const char *name = dns_resource_key_name(key);
+        if (dns_name_parent(&name) <= 0)
+                return false;
+
+        return dns_name_equal(name, "_tcp.local") || dns_name_equal(name, "_udp.local");
+}
+
 int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
         int r;
 
index 8ad4009ebf73683c16849f57fe0766c69520f4fa..156fa01873564e465a253c0d7e184daec7029a05 100644 (file)
@@ -334,6 +334,7 @@ DnsResourceKey* dns_resource_key_unref(DnsResourceKey *key);
 const char* dns_resource_key_name(const DnsResourceKey *key);
 bool dns_resource_key_is_address(const DnsResourceKey *key);
 bool dns_resource_key_is_dnssd_ptr(const DnsResourceKey *key);
+bool dns_resource_key_is_dnssd_two_label_ptr(const DnsResourceKey *key);
 int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b);
 int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain);
 int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain);
index a2b49f0b1e76538d77dc3be263bbf7219f7337b2..17bc8231962c78ea07706c2b8bf81d1ff85f3fcc 100644 (file)
@@ -1504,9 +1504,10 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) {
                         continue;
                 }
 
-                /* Collect service types for _services._dns-sd._udp.local RRs in a set */
+                /* Collect service types for _services._dns-sd._udp.local RRs in a set. Only two-label names
+                 * (not selective names) are considered according to RFC6763 § 9. */
                 if (!scope->announced &&
-                    dns_resource_key_is_dnssd_ptr(z->rr->key)) {
+                    dns_resource_key_is_dnssd_two_label_ptr(z->rr->key)) {
                         if (!set_contains(types, dns_resource_key_name(z->rr->key))) {
                                 r = set_ensure_put(&types, &dns_name_hash_ops, dns_resource_key_name(z->rr->key));
                                 if (r < 0)
@@ -1614,6 +1615,12 @@ int dns_scope_add_dnssd_services(DnsScope *scope) {
                 if (r < 0)
                         log_warning_errno(r, "Failed to add PTR record to MDNS zone: %m");
 
+                if (service->sub_ptr_rr) {
+                        r = dns_zone_put(&scope->zone, scope, service->sub_ptr_rr, false);
+                        if (r < 0)
+                                log_warning_errno(r, "Failed to add selective PTR record to MDNS zone: %m");
+                }
+
                 r = dns_zone_put(&scope->zone, scope, service->srv_rr, true);
                 if (r < 0)
                         log_warning_errno(r, "Failed to add SRV record to MDNS zone: %m");
@@ -1646,6 +1653,7 @@ int dns_scope_remove_dnssd_services(DnsScope *scope) {
 
         HASHMAP_FOREACH(service, scope->manager->dnssd_services) {
                 dns_zone_remove_rr(&scope->zone, service->ptr_rr);
+                dns_zone_remove_rr(&scope->zone, service->sub_ptr_rr);
                 dns_zone_remove_rr(&scope->zone, service->srv_rr);
                 LIST_FOREACH(items, txt_data, service->txt_data_items)
                         dns_zone_remove_rr(&scope->zone, txt_data->rr);
index 954841bb7c0a5bd18b6b582a3c5909f26ee1759f..2e3af0c445e10808786a6e008b77142b2a912f25 100644 (file)
@@ -181,6 +181,9 @@ DnsTransaction* dns_transaction_gc(DnsTransaction *t) {
         if (t->block_gc > 0)
                 return t;
 
+        if (t->wait_for_answer && IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING))
+                return t;
+
         if (set_isempty(t->notify_query_candidates) &&
             set_isempty(t->notify_query_candidates_done) &&
             set_isempty(t->notify_zone_items) &&
@@ -2298,7 +2301,7 @@ static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResource
         return 1;
 }
 
-static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) {
+static int dns_transaction_request_dnssec_rr_full(DnsTransaction *t, DnsResourceKey *key, DnsTransaction **ret) {
         _cleanup_(dns_answer_unrefp) DnsAnswer *a = NULL;
         DnsTransaction *aux;
         int r;
@@ -2329,11 +2332,19 @@ static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *
                 r = dns_transaction_go(aux);
                 if (r < 0)
                         return r;
+                if (ret)
+                        *ret = aux;
         }
 
         return 1;
 }
 
+static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) {
+        assert(t);
+        assert(key);
+        return dns_transaction_request_dnssec_rr_full(t, key, NULL);
+}
+
 static int dns_transaction_negative_trust_anchor_lookup(DnsTransaction *t, const char *name) {
         int r;
 
@@ -2434,6 +2445,8 @@ static bool dns_transaction_dnssec_supported_full(DnsTransaction *t) {
 int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
         DnsResourceRecord *rr;
 
+        /* Have we already requested a record that would be sufficient to validate an insecure delegation? */
+        bool chased_insecure = false;
         int r;
 
         assert(t);
@@ -2446,11 +2459,11 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
          * - For RRSIG we get the matching DNSKEY
          * - For DNSKEY we get the matching DS
          * - For unsigned SOA/NS we get the matching DS
-         * - For unsigned CNAME/DNAME/DS we get the parent SOA RR
-         * - For other unsigned RRs we get the matching SOA RR
+         * - For unsigned CNAME/DNAME/DS we get the parent DS RR
+         * - For other unsigned RRs we get the matching DS RR
          * - For SOA/NS queries with no matching response RR, and no NSEC/NSEC3, the DS RR
-         * - For DS queries with no matching response RRs, and no NSEC/NSEC3, the parent's SOA RR
-         * - For other queries with no matching response RRs, and no NSEC/NSEC3, the SOA RR
+         * - For DS queries with no matching response RRs, and no NSEC/NSEC3, the parent's DS RR
+         * - For other queries with no matching response RRs, and no NSEC/NSEC3, the DS RR
          */
 
         if (FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) || t->scope->dnssec_mode == DNSSEC_NO)
@@ -2477,6 +2490,7 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
                 case DNS_TYPE_RRSIG: {
                         /* For each RRSIG we request the matching DNSKEY */
                         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *dnskey = NULL;
+                        DnsTransaction *aux = NULL;
 
                         /* If this RRSIG is about a DNSKEY RR and the
                          * signer is the same as the owner, then we
@@ -2513,9 +2527,20 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
 
                         log_debug("Requesting DNSKEY to validate transaction %" PRIu16" (%s, RRSIG with key tag: %" PRIu16 ").",
                                   t->id, dns_resource_key_name(rr->key), rr->rrsig.key_tag);
-                        r = dns_transaction_request_dnssec_rr(t, dnskey);
+                        r = dns_transaction_request_dnssec_rr_full(t, dnskey, &aux);
                         if (r < 0)
                                 return r;
+
+                        /* If we are requesting a DNSKEY, we can anticipate that we will want the matching DS
+                         * in the near future. Let's request it in advance so we don't have to wait in the
+                         * common case. */
+                        if (aux) {
+                                _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds =
+                                        dns_resource_key_new(rr->key->class, DNS_TYPE_DS, dns_resource_key_name(dnskey));
+                                r = dns_transaction_request_dnssec_rr(t, ds);
+                                if (r < 0)
+                                        return r;
+                        }
                         break;
                 }
 
@@ -2590,6 +2615,7 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
                         if (r > 0)
                                 continue;
 
+                        chased_insecure = true;
                         ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, dns_resource_key_name(rr->key));
                         if (!ds)
                                 return -ENOMEM;
@@ -2606,11 +2632,11 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
                 case DNS_TYPE_DS:
                 case DNS_TYPE_CNAME:
                 case DNS_TYPE_DNAME: {
-                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
+                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
                         const char *name;
 
                         /* CNAMEs and DNAMEs cannot be located at a
-                         * zone apex, hence ask for the parent SOA for
+                         * zone apex, hence ask for the parent DS for
                          * unsigned CNAME/DNAME RRs, maybe that's the
                          * apex. But do all that only if this is
                          * actually a response to our original
@@ -2644,13 +2670,13 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
                         if (r == 0)
                                 continue;
 
-                        soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, name);
-                        if (!soa)
+                        ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, name);
+                        if (!ds)
                                 return -ENOMEM;
 
-                        log_debug("Requesting parent SOA to validate transaction %" PRIu16 " (%s, unsigned CNAME/DNAME/DS RRset).",
+                        log_debug("Requesting parent DS to validate transaction %" PRIu16 " (%s, unsigned CNAME/DNAME/DS RRset).",
                                   t->id, dns_resource_key_name(rr->key));
-                        r = dns_transaction_request_dnssec_rr(t, soa);
+                        r = dns_transaction_request_dnssec_rr(t, ds);
                         if (r < 0)
                                 return r;
 
@@ -2658,11 +2684,11 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
                 }
 
                 default: {
-                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
+                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
 
                         /* For other unsigned RRsets (including
                          * NSEC/NSEC3!), look for proof the zone is
-                         * unsigned, by requesting the SOA RR of the
+                         * unsigned, by requesting the DS RR of the
                          * zone. However, do so only if they are
                          * directly relevant to our original
                          * question. */
@@ -2679,13 +2705,13 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
                         if (r > 0)
                                 continue;
 
-                        soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, dns_resource_key_name(rr->key));
-                        if (!soa)
+                        ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, dns_resource_key_name(rr->key));
+                        if (!ds)
                                 return -ENOMEM;
 
-                        log_debug("Requesting SOA to validate transaction %" PRIu16 " (%s, unsigned non-SOA/NS RRset <%s>).",
+                        log_debug("Requesting DS to validate transaction %" PRIu16 " (%s, unsigned non-SOA/NS RRset <%s>).",
                                   t->id, dns_resource_key_name(rr->key), dns_resource_record_to_string(rr));
-                        r = dns_transaction_request_dnssec_rr(t, soa);
+                        r = dns_transaction_request_dnssec_rr(t, ds);
                         if (r < 0)
                                 return r;
                         break;
@@ -2700,49 +2726,38 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
         if (r < 0)
                 return r;
         if (r > 0) {
-                const char *name, *signed_status;
-                uint16_t type = 0;
-
-                name = dns_resource_key_name(dns_transaction_key(t));
-                signed_status = dns_answer_contains_nsec_or_nsec3(t->answer) ? "signed" : "unsigned";
+                const char *name = dns_resource_key_name(dns_transaction_key(t));
+                bool was_signed = dns_answer_contains_nsec_or_nsec3(t->answer);
 
-                /* If this was a SOA or NS request, then check if there's a DS RR for the same domain. Note that this
-                 * could also be used as indication that we are not at a zone apex, but in real world setups there are
-                 * too many broken DNS servers (Hello, incapdns.net!) where non-terminal zones return NXDOMAIN even
-                 * though they have further children. If this was a DS request, then it's signed when the parent zone
-                 * is signed, hence ask the parent SOA in that case. If this was any other RR then ask for the SOA RR,
-                 * to see if that is signed. */
-
-                if (dns_transaction_key(t)->type == DNS_TYPE_DS) {
-                        r = dns_name_parent(&name);
-                        if (r > 0) {
-                                type = DNS_TYPE_SOA;
-                                log_debug("Requesting parent SOA (%s %s) to validate transaction %" PRIu16 " (%s, %s empty DS response).",
-                                          special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), name, t->id,
-                                          dns_resource_key_name(dns_transaction_key(t)), signed_status);
-                        } else
+                /* If the response is empty, seek the DS for this name, just in case we're at a zone cut
+                 * already, unless we just requested the DS, in which case we have to ask the parent to make
+                 * progress.
+                 *
+                 * If this was an SOA or NS request, we could also skip to the parent, but in real world
+                 * setups there are too many broken DNS servers (Hello, incapdns.net!) where non-terminal
+                 * zones return NXDOMAIN even though they have further children. */
+
+                if (chased_insecure || was_signed)
+                        /* In this case we already requested what we need above. */
+                        name = NULL;
+                else if (dns_transaction_key(t)->type == DNS_TYPE_DS)
+                        /* If the DS response is empty, we'll walk up the dns labels requesting DS until we
+                         * find a referral to the SOA or hit it anyway and get a positive DS response. */
+                        if (dns_name_parent(&name) <= 0)
                                 name = NULL;
 
-                } else if (IN_SET(dns_transaction_key(t)->type, DNS_TYPE_SOA, DNS_TYPE_NS)) {
-
-                        type = DNS_TYPE_DS;
-                        log_debug("Requesting DS (%s %s) to validate transaction %" PRIu16 " (%s, %s empty SOA/NS response).",
-                                  special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), name, t->id, name, signed_status);
-
-                } else {
-                        type = DNS_TYPE_SOA;
-                        log_debug("Requesting SOA (%s %s) to validate transaction %" PRIu16 " (%s, %s empty non-SOA/NS/DS response).",
-                                  special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), name, t->id, name, signed_status);
-                }
-
                 if (name) {
-                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL;
+                        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL;
+
+                        log_debug("Requesting DS (%s %s) to validate transaction %" PRIu16 " (%s empty response).",
+                                  special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), name, t->id,
+                                  dns_resource_key_name(dns_transaction_key(t)));
 
-                        soa = dns_resource_key_new(dns_transaction_key(t)->class, type, name);
-                        if (!soa)
+                        ds = dns_resource_key_new(dns_transaction_key(t)->class, DNS_TYPE_DS, name);
+                        if (!ds)
                                 return -ENOMEM;
 
-                        r = dns_transaction_request_dnssec_rr(t, soa);
+                        r = dns_transaction_request_dnssec_rr(t, ds);
                         if (r < 0)
                                 return r;
                 }
@@ -2822,7 +2837,6 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
                 DnsTransaction *dt;
 
                 /* For SOA or NS RRs we look for a matching DS transaction */
-
                 SET_FOREACH(dt, t->dnssec_transactions) {
 
                         if (dns_transaction_key(dt)->class != rr->key->class)
@@ -2830,7 +2844,7 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
                         if (dns_transaction_key(dt)->type != DNS_TYPE_DS)
                                 continue;
 
-                        r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), dns_resource_key_name(rr->key));
+                        r = dns_name_endswith(dns_resource_key_name(rr->key), dns_resource_key_name(dns_transaction_key(dt)));
                         if (r < 0)
                                 return r;
                         if (r == 0)
@@ -2859,16 +2873,16 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
                 DnsTransaction *dt;
 
                 /*
-                 * CNAME/DNAME RRs cannot be located at a zone apex, hence look directly for the parent SOA.
+                 * CNAME/DNAME RRs cannot be located at a zone apex, hence look directly for the parent DS.
                  *
-                 * DS RRs are signed if the parent is signed, hence also look at the parent SOA
+                 * DS RRs are signed if the parent is signed, hence also look at the parent DS
                  */
 
                 SET_FOREACH(dt, t->dnssec_transactions) {
 
                         if (dns_transaction_key(dt)->class != rr->key->class)
                                 continue;
-                        if (dns_transaction_key(dt)->type != DNS_TYPE_SOA)
+                        if (dns_transaction_key(dt)->type != DNS_TYPE_DS)
                                 continue;
 
                         if (!parent) {
@@ -2886,7 +2900,7 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
                                 }
                         }
 
-                        r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), parent);
+                        r = dns_name_endswith(parent, dns_resource_key_name(dns_transaction_key(dt)));
                         if (r < 0)
                                 return r;
                         if (r == 0)
@@ -2901,25 +2915,26 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
         default: {
                 DnsTransaction *dt;
 
-                /* Any other kind of RR (including DNSKEY/NSEC/NSEC3). Let's see if our SOA lookup was authenticated */
+                /* Any other kind of RR (including DNSKEY/NSEC/NSEC3). Let's see if our DS lookup was authenticated */
 
                 SET_FOREACH(dt, t->dnssec_transactions) {
-
                         if (dns_transaction_key(dt)->class != rr->key->class)
                                 continue;
-                        if (dns_transaction_key(dt)->type != DNS_TYPE_SOA)
+                        if (dns_transaction_key(dt)->type != DNS_TYPE_DS)
                                 continue;
 
-                        r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), dns_resource_key_name(rr->key));
+                        r = dns_name_endswith(dns_resource_key_name(rr->key), dns_resource_key_name(dns_transaction_key(dt)));
                         if (r < 0)
                                 return r;
                         if (r == 0)
                                 continue;
 
-                        /* We found the transaction that was supposed to find the SOA RR for us. It was
-                         * successful, but found no RR for us. This means we are not at a zone cut. In this
-                         * case, we require authentication if the SOA lookup was authenticated too. */
-                        return FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED);
+                        if (!FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
+                                return false;
+
+                        /* We expect this to be signed when the DS record exists, and don't expect it to be
+                         * signed when the DS record is proven not to exist. */
+                        return dns_answer_match_key(dt->answer, dns_transaction_key(dt), NULL);
                 }
 
                 return true;
@@ -2989,7 +3004,6 @@ static int dns_transaction_requires_nsec(DnsTransaction *t) {
         char key_str[DNS_RESOURCE_KEY_STRING_MAX];
         DnsTransaction *dt;
         const char *name;
-        uint16_t type = 0;
         int r;
 
         assert(t);
@@ -3024,43 +3038,37 @@ static int dns_transaction_requires_nsec(DnsTransaction *t) {
 
         name = dns_resource_key_name(dns_transaction_key(t));
 
-        if (dns_transaction_key(t)->type == DNS_TYPE_DS) {
-
-                /* We got a negative reply for this DS lookup? DS RRs are signed when their parent zone is signed,
-                 * hence check the parent SOA in this case. */
-
+        if (IN_SET(dns_transaction_key(t)->type, DNS_TYPE_DS, DNS_TYPE_CNAME, DNS_TYPE_DNAME)) {
+                /* We got a negative reply for this DS/CNAME/DNAME lookup? Check the parent in this case to
+                 * see if this answer should have been signed. */
                 r = dns_name_parent(&name);
                 if (r < 0)
                         return r;
                 if (r == 0)
                         return true;
+        }
 
-                type = DNS_TYPE_SOA;
-
-        } else if (IN_SET(dns_transaction_key(t)->type, DNS_TYPE_SOA, DNS_TYPE_NS))
-                /* We got a negative reply for this SOA/NS lookup? If so, check if there's a DS RR for this */
-                type = DNS_TYPE_DS;
-        else
-                /* For all other negative replies, check for the SOA lookup */
-                type = DNS_TYPE_SOA;
-
-        /* For all other RRs we check the SOA on the same level to see
+        /* For all other RRs we check the DS on the same level to see
          * if it's signed. */
 
         SET_FOREACH(dt, t->dnssec_transactions) {
-
                 if (dns_transaction_key(dt)->class != dns_transaction_key(t)->class)
                         continue;
-                if (dns_transaction_key(dt)->type != type)
+                if (dns_transaction_key(dt)->type != DNS_TYPE_DS)
                         continue;
 
-                r = dns_name_equal(dns_resource_key_name(dns_transaction_key(dt)), name);
+                r = dns_name_endswith(name, dns_resource_key_name(dns_transaction_key(dt)));
                 if (r < 0)
                         return r;
                 if (r == 0)
                         continue;
 
-                return FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED);
+                if (!FLAGS_SET(dt->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
+                        return false;
+
+                /* We expect this to be signed when the DS record exists, and don't expect it to be signed
+                 * when the DS record is proven not to exist. */
+                return dns_answer_match_key(dt->answer, dns_transaction_key(dt), NULL);
         }
 
         /* If in doubt, require NSEC/NSEC3 */
index 6de4cdd749122848d2382287604fa29ca6eed7df..30d2167d645dd35d85c7799a1fd9cb497982197e 100644 (file)
@@ -136,6 +136,11 @@ struct DnsTransaction {
 
         unsigned block_gc;
 
+        /* Set when we're willing to let this transaction live beyond it's usefulness for the original query,
+         * for caching purposes. This blocks gc while there is still a chance we might still receive an
+         * answer. */
+        bool wait_for_answer;
+
         LIST_FIELDS(DnsTransaction, transactions_by_scope);
         LIST_FIELDS(DnsTransaction, transactions_by_stream);
         LIST_FIELDS(DnsTransaction, transactions_by_key);
index b2deef5694e30d7402bd0543c4ebcbafe5337a3f..bdb3c2a893ea54b9894dcc190d7d559ed25486f3 100644 (file)
@@ -40,6 +40,7 @@ int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_
                                 log_warning_errno(r, "Failed to send goodbye messages in IPv4 scope: %m");
 
                         dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, s->ptr_rr);
+                        dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, s->sub_ptr_rr);
                         dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, s->srv_rr);
                         LIST_FOREACH(items, txt_data, s->txt_data_items)
                                 dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, txt_data->rr);
@@ -51,6 +52,7 @@ int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_
                                 log_warning_errno(r, "Failed to send goodbye messages in IPv6 scope: %m");
 
                         dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, s->ptr_rr);
+                        dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, s->sub_ptr_rr);
                         dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, s->srv_rr);
                         LIST_FOREACH(items, txt_data, s->txt_data_items)
                                 dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, txt_data->rr);
index f10eae3ceefd6dde4b036ced4dc62fe0469e6178..e78573bec0a40b1e13ec607e66083e3d2137a9b1 100644 (file)
@@ -16,10 +16,11 @@ struct ConfigPerfItem;
 %struct-type
 %includes
 %%
-Service.Name,     config_parse_dnssd_service_name, 0,                 0
-Service.Type,     config_parse_dnssd_service_type, 0,                 0
-Service.Port,     config_parse_ip_port,            0,                 offsetof(DnssdService, port)
-Service.Priority, config_parse_uint16,             0,                 offsetof(DnssdService, priority)
-Service.Weight,   config_parse_uint16,             0,                 offsetof(DnssdService, weight)
-Service.TxtText,  config_parse_dnssd_txt,          DNS_TXT_ITEM_TEXT, 0
-Service.TxtData,  config_parse_dnssd_txt,          DNS_TXT_ITEM_DATA, 0
+Service.Name,     config_parse_dnssd_service_name,    0,                 0
+Service.Type,     config_parse_dnssd_service_type,    0,                 0
+Service.SubType,  config_parse_dnssd_service_subtype, 0,                 0
+Service.Port,     config_parse_ip_port,               0,                 offsetof(DnssdService, port)
+Service.Priority, config_parse_uint16,                0,                 offsetof(DnssdService, priority)
+Service.Weight,   config_parse_uint16,                0,                 offsetof(DnssdService, weight)
+Service.TxtText,  config_parse_dnssd_txt,             DNS_TXT_ITEM_TEXT, 0
+Service.TxtData,  config_parse_dnssd_txt,             DNS_TXT_ITEM_DATA, 0
index 994771eca733de3600ba85298f899ef6b942c994..8790755d3b6044ad6abe158a86a4848bddbe06bc 100644 (file)
@@ -43,6 +43,7 @@ DnssdService *dnssd_service_free(DnssdService *service) {
                 hashmap_remove(service->manager->dnssd_services, service->name);
 
         dns_resource_record_unref(service->ptr_rr);
+        dns_resource_record_unref(service->sub_ptr_rr);
         dns_resource_record_unref(service->srv_rr);
 
         dnssd_txtdata_free_all(service->txt_data_items);
@@ -50,6 +51,7 @@ DnssdService *dnssd_service_free(DnssdService *service) {
         free(service->filename);
         free(service->name);
         free(service->type);
+        free(service->subtype);
         free(service->name_template);
 
         return mfree(service);
@@ -138,16 +140,10 @@ static int dnssd_service_load(Manager *manager, const char *filename) {
 
 static int specifier_dnssd_hostname(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
         const Manager *m = ASSERT_PTR(userdata);
-        char *n;
 
         assert(m->llmnr_hostname);
 
-        n = strdup(m->llmnr_hostname);
-        if (!n)
-                return -ENOMEM;
-
-        *ret = n;
-        return 0;
+        return strdup_to(ret, m->llmnr_hostname);
 }
 
 int dnssd_render_instance_name(Manager *m, DnssdService *s, char **ret) {
@@ -208,7 +204,7 @@ int dnssd_load(Manager *manager) {
 }
 
 int dnssd_update_rrs(DnssdService *s) {
-        _cleanup_free_ char *n = NULL, *service_name = NULL, *full_name = NULL;
+        _cleanup_free_ char *n = NULL, *service_name = NULL, *full_name = NULL, *sub_name = NULL, *selective_name = NULL;
         int r;
 
         assert(s);
@@ -216,6 +212,7 @@ int dnssd_update_rrs(DnssdService *s) {
         assert(s->manager);
 
         s->ptr_rr = dns_resource_record_unref(s->ptr_rr);
+        s->sub_ptr_rr = dns_resource_record_unref(s->sub_ptr_rr);
         s->srv_rr = dns_resource_record_unref(s->srv_rr);
         LIST_FOREACH(items, txt_data, s->txt_data_items)
                 txt_data->rr = dns_resource_record_unref(txt_data->rr);
@@ -230,6 +227,14 @@ int dnssd_update_rrs(DnssdService *s) {
         r = dns_name_concat(n, service_name, 0, &full_name);
         if (r < 0)
                 return r;
+        if (s->subtype) {
+                r = dns_name_concat("_sub", service_name, 0, &sub_name);
+                if (r < 0)
+                        return r;
+                r = dns_name_concat(s->subtype, sub_name, 0, &selective_name);
+                if (r < 0)
+                        return r;
+        }
 
         LIST_FOREACH(items, txt_data, s->txt_data_items) {
                 txt_data->rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_TXT,
@@ -253,6 +258,17 @@ int dnssd_update_rrs(DnssdService *s) {
         if (!s->ptr_rr->ptr.name)
                 goto oom;
 
+        if (selective_name) {
+                s->sub_ptr_rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, selective_name);
+                if (!s->sub_ptr_rr)
+                        goto oom;
+
+                s->sub_ptr_rr->ttl = MDNS_DEFAULT_TTL;
+                s->sub_ptr_rr->ptr.name = strdup(full_name);
+                if (!s->sub_ptr_rr->ptr.name)
+                        goto oom;
+        }
+
         s->srv_rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SRV,
                                                  full_name);
         if (!s->srv_rr)
@@ -272,6 +288,7 @@ oom:
         LIST_FOREACH(items, txt_data, s->txt_data_items)
                 txt_data->rr = dns_resource_record_unref(txt_data->rr);
         s->ptr_rr = dns_resource_record_unref(s->ptr_rr);
+        s->sub_ptr_rr = dns_resource_record_unref(s->sub_ptr_rr);
         s->srv_rr = dns_resource_record_unref(s->srv_rr);
         return -ENOMEM;
 }
index e978a0d5fc6ec4e16522bf05f7831a23144ade8f..970f2ba3c86764c0a32d2d14bafe9eb540c71a39 100644 (file)
@@ -29,11 +29,13 @@ struct DnssdService {
         char *name;
         char *name_template;
         char *type;
+        char *subtype;
         uint16_t port;
         uint16_t priority;
         uint16_t weight;
 
         DnsResourceRecord *ptr_rr;
+        DnsResourceRecord *sub_ptr_rr;
         DnsResourceRecord *srv_rr;
 
         /* Section 6.8 of RFC 6763 allows having service
index 95336b86fe5a7143ec1ead09b56317f853e313a9..221b441fac82df4770447ee037044b95c1b70897 100644 (file)
@@ -12,12 +12,12 @@ install_emptydir(bindir)
 
 meson.add_install_script(sh, '-c',
                              ln_s.format(bindir / 'systemd-run',
-                                         bindir / 'uid0'))
+                                         bindir / 'run0'))
 
 custom_target(
-        'systemd-uid0',
-        input : 'systemd-uid0.in',
-        output : 'systemd-uid0',
+        'systemd-run0',
+        input : 'systemd-run0.in',
+        output : 'systemd-run0',
         command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'],
         install : pamconfdir != 'no',
         install_dir : pamconfdir)
index c0c65b2ea1fa12eb5faf8129a7a3f550a9c57003..e8dc3388c05e9650c9ad9a456b66a85b27c08a27 100644 (file)
@@ -159,7 +159,7 @@ static int help_sudo_mode(void) {
         _cleanup_free_ char *link = NULL;
         int r;
 
-        r = terminal_urlify_man("uid0", "1", &link);
+        r = terminal_urlify_man("run0", "1", &link);
         if (r < 0)
                 return log_oom();
 
@@ -743,7 +743,7 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
                 ARG_BACKGROUND,
         };
 
-        /* If invoked as "uid0" binary, let's expose a more sudo-like interface. We add various extensions
+        /* If invoked as "run0" binary, let's expose a more sudo-like interface. We add various extensions
          * though (but limit the extension to long options). */
 
         static const struct option options[] = {
@@ -943,7 +943,7 @@ static int parse_argv_sudo_mode(int argc, char *argv[]) {
         if (strv_extendf(&arg_property, "LogExtraFields=ELEVATED_USER=%s", un) < 0)
                 return log_oom();
 
-        if (strv_extend(&arg_property, "PAMName=systemd-uid0") < 0)
+        if (strv_extend(&arg_property, "PAMName=systemd-run0") < 0)
                 return log_oom();
 
         if (!arg_background && arg_stdio == ARG_STDIO_PTY) {
@@ -2262,7 +2262,7 @@ static int run(int argc, char* argv[]) {
         log_parse_environment();
         log_open();
 
-        if (invoked_as(argv, "uid0"))
+        if (invoked_as(argv, "run0"))
                 r = parse_argv_sudo_mode(argc, argv);
         else
                 r = parse_argv(argc, argv);
similarity index 96%
rename from src/run/systemd-uid0.in
rename to src/run/systemd-run0.in
index 57bd5e38b92a97b53b1a0dcba8ca8a14affb368d..11f830b7b08fa6cc948c5412dd549d6c84e3a2af 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 # This file is part of systemd.
 #
-# Used by uid0 sessions
+# Used by run0 sessions
 
 {% if ENABLE_HOMED %}
 -account sufficient pam_systemd_home.so
index 2d5846a06ffe662d1fb1a6e88d76463c4c6bd3cd..ba8aee335541aab8add01185327f622b6b5bc8a8 100644 (file)
@@ -28,6 +28,7 @@
 #include "random-util.h"
 #include "sparse-endian.h"
 #include "stat-util.h"
+#include "tmpfile-util.h"
 #include "tpm2-util.h"
 #include "user-util.h"
 #include "varlink.h"
@@ -377,22 +378,9 @@ static int make_credential_host_secret(
         assert(dfd >= 0);
         assert(fn);
 
-        /* For non-root users creating a temporary file using the openat(2) over "." will fail later, in the
-         * linkat(2) step at the end.  The reason is that linkat(2) requires the CAP_DAC_READ_SEARCH
-         * capability when it uses the AT_EMPTY_PATH flag. */
-        if (have_effective_cap(CAP_DAC_READ_SEARCH) > 0) {
-                fd = openat(dfd, ".", O_CLOEXEC|O_WRONLY|O_TMPFILE, 0400);
-                if (fd < 0)
-                        log_debug_errno(errno, "Failed to create temporary credential file with O_TMPFILE, proceeding without: %m");
-        }
-        if (fd < 0) {
-                if (asprintf(&t, "credential.secret.%016" PRIx64, random_u64()) < 0)
-                        return -ENOMEM;
-
-                fd = openat(dfd, t, O_CLOEXEC|O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0400);
-                if (fd < 0)
-                        return -errno;
-        }
+        fd = open_tmpfile_linkable_at(dfd, fn, O_CLOEXEC|O_WRONLY, &t);
+        if (fd < 0)
+                return log_debug_errno(fd, "Failed to create temporary file for credential host secret: %m");
 
         r = chattr_secret(fd, 0);
         if (r < 0)
@@ -412,26 +400,21 @@ static int make_credential_host_secret(
         if (r < 0)
                 goto fail;
 
-        if (fsync(fd) < 0) {
+        if (fchmod(fd, 0400) < 0) {
                 r = -errno;
                 goto fail;
         }
 
-        warn_not_encrypted(fd, flags, dirname, fn);
-
-        if (t) {
-                r = rename_noreplace(dfd, t, dfd, fn);
-                if (r < 0)
-                        goto fail;
-
-                t = mfree(t);
-        } else if (linkat(fd, "", dfd, fn, AT_EMPTY_PATH) < 0) {
+        if (fsync(fd) < 0) {
                 r = -errno;
                 goto fail;
         }
 
-        if (fsync(dfd) < 0) {
-                r = -errno;
+        warn_not_encrypted(fd, flags, dirname, fn);
+
+        r = link_tmpfile_at(fd, dfd, t, fn, LINK_TMPFILE_SYNC);
+        if (r < 0) {
+                log_debug_errno(r, "Failed to link host key into place: %m");
                 goto fail;
         }
 
@@ -439,10 +422,8 @@ static int make_credential_host_secret(
                 void *copy;
 
                 copy = memdup(buf.data, sizeof(buf.data));
-                if (!copy) {
-                        r = -ENOMEM;
-                        goto fail;
-                }
+                if (!copy)
+                        return -ENOMEM;
 
                 *ret = IOVEC_MAKE(copy, sizeof(buf.data));
         }
index eac3641abd56196af2c8a32367c61b51c87c349f..a0832c98281faffdbd3dbbc9ac24141b86d6f0b4 100644 (file)
@@ -268,16 +268,8 @@ int probe_filesystem_full(
         (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
 
         if (fstype) {
-                char *t;
-
                 log_debug("Probed fstype '%s' on partition %s.", fstype, path);
-
-                t = strdup(fstype);
-                if (!t)
-                        return -ENOMEM;
-
-                *ret_fstype = t;
-                return 1;
+                return strdup_to_full(ret_fstype, fstype);
         }
 
 not_found:
@@ -2286,19 +2278,19 @@ int dissected_image_mount_and_warn(
 
         r = dissected_image_mount(m, where, uid_shift, uid_range, userns_fd, flags);
         if (r == -ENXIO)
-                return log_error_errno(r, "Not root file system found in image.");
+                return log_error_errno(r, "Failed to mount image: No root file system found in image.");
         if (r == -EMEDIUMTYPE)
-                return log_error_errno(r, "No suitable os-release/extension-release file in image found.");
+                return log_error_errno(r, "Failed to mount image: No suitable os-release/extension-release file in image found.");
         if (r == -EUNATCH)
-                return log_error_errno(r, "Encrypted file system discovered, but decryption not requested.");
+                return log_error_errno(r, "Failed to mount image: Encrypted file system discovered, but decryption not requested.");
         if (r == -EUCLEAN)
-                return log_error_errno(r, "File system check on image failed.");
+                return log_error_errno(r, "Failed to mount image: File system check on image failed.");
         if (r == -EBUSY)
-                return log_error_errno(r, "File system already mounted elsewhere.");
+                return log_error_errno(r, "Failed to mount image: File system already mounted elsewhere.");
         if (r == -EAFNOSUPPORT)
-                return log_error_errno(r, "File system type not supported or not known.");
+                return log_error_errno(r, "Failed to mount image: File system type not supported or not known.");
         if (r == -EIDRM)
-                return log_error_errno(r, "File system is too uncommon, refused.");
+                return log_error_errno(r, "Failed to mount image: File system is too uncommon, refused.");
         if (r < 0)
                 return log_error_errno(r, "Failed to mount image: %m");
 
index 909b4cdcc93aeedce4d5e43deedea64b26ad8c3b..ba24a77dad993feecbe4d4aa8bfc867b765bc417 100644 (file)
@@ -980,6 +980,29 @@ bool dns_service_name_is_valid(const char *name) {
         return true;
 }
 
+bool dns_subtype_name_is_valid(const char *name) {
+        size_t l;
+
+        /* This more or less implements RFC 6763, Section 7.2 */
+
+        if (!name)
+                return false;
+
+        if (!utf8_is_valid(name))
+                return false;
+
+        if (string_has_cc(name, NULL))
+                return false;
+
+        l = strlen(name);
+        if (l <= 0)
+                return false;
+        if (l > DNS_LABEL_MAX)
+                return false;
+
+        return true;
+}
+
 int dns_service_join(const char *name, const char *type, const char *domain, char **ret) {
         char escaped[DNS_LABEL_ESCAPED_MAX];
         _cleanup_free_ char *n = NULL;
index 331fb89637c52f30fca61172d79a0e7d94e64391..8ad00d6e4bc5a757ecf6bbe76b2d519f1d826f89 100644 (file)
@@ -83,6 +83,7 @@ int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, boo
 bool dns_srv_type_is_valid(const char *name);
 bool dnssd_srv_type_is_valid(const char *name);
 bool dns_service_name_is_valid(const char *name);
+bool dns_subtype_name_is_valid(const char *name);
 
 int dns_service_join(const char *name, const char *type, const char *domain, char **ret);
 int dns_service_split(const char *joined, char **ret_name, char **ret_type, char **ret_domain);
index dce9e005fee495924740772e2b7f1d19c0b70d49..1e100c35ef530299230d767df15b7e99c4e7fe9c 100644 (file)
@@ -182,7 +182,6 @@ int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret) {
         struct ifreq ifr = {
                 .ifr_data = (void*) &ecmd,
         };
-        char *d;
         int r;
 
         assert(ethtool_fd);
@@ -201,12 +200,7 @@ int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret) {
         if (isempty(ecmd.driver))
                 return -ENODATA;
 
-        d = strdup(ecmd.driver);
-        if (!d)
-                return -ENOMEM;
-
-        *ret = d;
-        return 0;
+        return strdup_to(ret, ecmd.driver);
 }
 
 int ethtool_get_link_info(
index c538506eaf616e626284884bdd58584c77a05e32..6cfd4b54bf631c053fe84088b4223725218b887b 100644 (file)
@@ -6,6 +6,8 @@
 #include <sys/utsname.h>
 #include <unistd.h>
 
+#include "sd-daemon.h"
+
 #include "alloc-util.h"
 #include "creds-util.h"
 #include "fd-util.h"
@@ -13,6 +15,7 @@
 #include "fs-util.h"
 #include "hostname-setup.h"
 #include "hostname-util.h"
+#include "initrd-util.h"
 #include "log.h"
 #include "macro.h"
 #include "proc-cmdline.h"
@@ -24,7 +27,8 @@ static int sethostname_idempotent_full(const char *s, bool really) {
 
         assert(s);
 
-        assert_se(uname(&u) >= 0);
+        if (uname(&u) < 0)
+                return -errno;
 
         if (streq_ptr(s, u.nodename))
                 return 0;
@@ -41,34 +45,33 @@ int sethostname_idempotent(const char *s) {
 }
 
 int shorten_overlong(const char *s, char **ret) {
-        char *h, *p;
+        _cleanup_free_ char *h = NULL;
 
         /* Shorten an overlong name to HOST_NAME_MAX or to the first dot,
          * whatever comes earlier. */
 
         assert(s);
+        assert(ret);
 
         h = strdup(s);
         if (!h)
                 return -ENOMEM;
 
         if (hostname_is_valid(h, 0)) {
-                *ret = h;
+                *ret = TAKE_PTR(h);
                 return 0;
         }
 
-        p = strchr(h, '.');
+        char *p = strchr(h, '.');
         if (p)
                 *p = 0;
 
         strshorten(h, HOST_NAME_MAX);
 
-        if (!hostname_is_valid(h, 0)) {
-                free(h);
+        if (!hostname_is_valid(h, /* flags= */ 0))
                 return -EDOM;
-        }
 
-        *ret = h;
+        *ret = TAKE_PTR(h);
         return 1;
 }
 
@@ -147,74 +150,64 @@ void hostname_update_source_hint(const char *hostname, HostnameSource source) {
                 r = write_string_file("/run/systemd/default-hostname", hostname,
                                       WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_ATOMIC);
                 if (r < 0)
-                        log_warning_errno(r, "Failed to create \"/run/systemd/default-hostname\": %m");
+                        log_warning_errno(r, "Failed to create \"/run/systemd/default-hostname\", ignoring: %m");
         } else
                 unlink_or_warn("/run/systemd/default-hostname");
 }
 
 int hostname_setup(bool really) {
-        _cleanup_free_ char *b = NULL;
-        const char *hn = NULL;
+        _cleanup_free_ char *hn = NULL;
         HostnameSource source;
         bool enoent = false;
         int r;
 
-        r = proc_cmdline_get_key("systemd.hostname", 0, &b);
+        r = proc_cmdline_get_key("systemd.hostname", 0, &hn);
         if (r < 0)
                 log_warning_errno(r, "Failed to retrieve system hostname from kernel command line, ignoring: %m");
         else if (r > 0) {
-                if (hostname_is_valid(b, VALID_HOSTNAME_TRAILING_DOT)) {
-                        hn = b;
+                if (hostname_is_valid(hn, VALID_HOSTNAME_TRAILING_DOT))
                         source = HOSTNAME_TRANSIENT;
-                else  {
-                        log_warning("Hostname specified on kernel command line is invalid, ignoring: %s", b);
-                        b = mfree(b);
+                else  {
+                        log_warning("Hostname specified on kernel command line is invalid, ignoring: %s", hn);
+                        hn = mfree(hn);
                 }
         }
 
         if (!hn) {
-                r = read_etc_hostname(NULL, &b);
-                if (r < 0) {
-                        if (r == -ENOENT)
-                                enoent = true;
-                        else
-                                log_warning_errno(r, "Failed to read configured hostname: %m");
-                } else {
-                        hn = b;
+                r = read_etc_hostname(NULL, &hn);
+                if (r == -ENOENT)
+                        enoent = true;
+                else if (r < 0)
+                        log_warning_errno(r, "Failed to read configured hostname, ignoring: %m");
+                else
                         source = HOSTNAME_STATIC;
-                }
         }
 
         if (!hn) {
-                r = acquire_hostname_from_credential(&b);
-                if (r >= 0) {
-                        hn = b;
+                r = acquire_hostname_from_credential(&hn);
+                if (r >= 0)
                         source = HOSTNAME_TRANSIENT;
-                }
         }
 
         if (!hn) {
-                _cleanup_free_ char *buf = NULL;
-
                 /* Don't override the hostname if it is already set and not explicitly configured */
 
-                r = gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST, &buf);
+                r = gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST, &hn);
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r >= 0) {
-                        log_debug("No hostname configured, leaving existing hostname <%s> in place.", buf);
-                        return 0;
+                        log_debug("No hostname configured, leaving existing hostname <%s> in place.", hn);
+                        goto finish;
                 }
 
                 if (enoent)
                         log_info("No hostname configured, using default hostname.");
 
-                hn = b = get_default_hostname();
+                hn = get_default_hostname();
                 if (!hn)
                         return log_oom();
 
                 source = HOSTNAME_DEFAULT;
-
         }
 
         r = sethostname_idempotent_full(hn, really);
@@ -230,7 +223,11 @@ int hostname_setup(bool really) {
         if (really)
                 hostname_update_source_hint(hn, source);
 
-        return r;
+finish:
+        if (!in_initrd())
+                (void) sd_notifyf(/* unset_environment= */ false, "X_SYSTEMD_HOSTNAME=%s", hn);
+
+        return 0;
 }
 
 static const char* const hostname_source_table[] = {
index 3cc709308da87e1db775b1a9530aec86e0eff6cc..bdb44b348fbe58d5c56154ea3f085b9405780685 100644 (file)
@@ -37,16 +37,11 @@ static int specifier_prefix_and_instance(char specifier, const void *data, const
 
 static int specifier_name(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
         const InstallInfo *i = ASSERT_PTR(userdata);
-        char *ans;
 
         if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE) && i->default_instance)
                 return unit_name_replace_instance(i->name, i->default_instance, ret);
 
-        ans = strdup(i->name);
-        if (!ans)
-                return -ENOMEM;
-        *ret = ans;
-        return 0;
+        return strdup_to(ret, i->name);
 }
 
 static int specifier_prefix(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
@@ -86,14 +81,10 @@ static int specifier_last_component(char specifier, const void *data, const char
                 return r;
 
         dash = strrchr(prefix, '-');
-        if (dash) {
-                dash = strdup(dash + 1);
-                if (!dash)
-                        return -ENOMEM;
-                *ret = dash;
-        } else
-                *ret = TAKE_PTR(prefix);
+        if (dash)
+                return strdup_to(ret, dash + 1);
 
+        *ret = TAKE_PTR(prefix);
         return 0;
 }
 
index 81f898f28a477b07df9e33df97857e6ee59867cb..8fe0165225ccbd6bf7fa6f053013fc720db6b7ca 100644 (file)
@@ -1941,7 +1941,7 @@ static int install_info_symlink_alias(
         assert(config_path);
 
         STRV_FOREACH(s, info->aliases) {
-                _cleanup_free_ char *alias_path = NULL, *dst = NULL, *dst_updated = NULL;
+                _cleanup_free_ char *alias_path = NULL, *alias_target = NULL, *dst = NULL, *dst_updated = NULL;
 
                 r = install_name_printf(scope, info, *s, &dst);
                 if (r < 0) {
@@ -1960,6 +1960,18 @@ static int install_info_symlink_alias(
                 if (!alias_path)
                         return -ENOMEM;
 
+                r = in_search_path(lp, info->path);
+                if (r < 0)
+                        return r;
+                if (r == 0) {
+                        /* The unit path itself is outside of the search path. To
+                         * correctly apply the alias, we need the alias symlink to
+                         * point to the symlink that was created in the search path. */
+                        alias_target = path_join(config_path, info->name);
+                        if (!alias_target)
+                                return -ENOMEM;
+                }
+
                 bool broken;
                 r = chase(alias_path, lp->root_dir, CHASE_NONEXISTENT, /* ret_path = */ NULL, /* ret_fd = */ NULL);
                 if (r < 0 && r != -ENOENT) {
@@ -1968,7 +1980,7 @@ static int install_info_symlink_alias(
                 }
                 broken = r == 0; /* symlink target does not exist? */
 
-                RET_GATHER(ret, create_symlink(lp, info->path, alias_path, force || broken, changes, n_changes));
+                RET_GATHER(ret, create_symlink(lp, alias_target ?: info->path, alias_path, force || broken, changes, n_changes));
         }
 
         return ret;
@@ -3030,17 +3042,16 @@ int unit_file_set_default(
 int unit_file_get_default(
                 RuntimeScope scope,
                 const char *root_dir,
-                char **name) {
+                char **ret) {
 
         _cleanup_(lookup_paths_done) LookupPaths lp = {};
         _cleanup_(install_context_done) InstallContext ctx = { .scope = scope };
         InstallInfo *info;
-        char *n;
         int r;
 
         assert(scope >= 0);
         assert(scope < _RUNTIME_SCOPE_MAX);
-        assert(name);
+        assert(ret);
 
         r = lookup_paths_init(&lp, scope, 0, root_dir);
         if (r < 0)
@@ -3051,12 +3062,7 @@ int unit_file_get_default(
         if (r < 0)
                 return r;
 
-        n = strdup(info->name);
-        if (!n)
-                return -ENOMEM;
-
-        *name = n;
-        return 0;
+        return strdup_to(ret, info->name);
 }
 
 int unit_file_lookup_state(
@@ -3209,11 +3215,9 @@ int unit_file_exists_full(RuntimeScope scope, const LookupPaths *lp, const char
         if (ret_path) {
                 assert(info);
 
-                _cleanup_free_ char *p = strdup(info->path);
-                if (!p)
-                        return -ENOMEM;
-
-                *ret_path = TAKE_PTR(p);
+                r = strdup_to(ret_path, info->path);
+                if (r < 0)
+                        return r;
         }
 
         return 1;
index a09557f69f244c1d6dfd407120c2015d2240b90b..8cce6dddfe2adff1af147ad296e89ad0e98d8ba2 100644 (file)
@@ -175,7 +175,7 @@ int unit_file_set_default(
 int unit_file_get_default(
                 RuntimeScope scope,
                 const char *root_dir,
-                char **name);
+                char **ret);
 int unit_file_add_dependency(
                 RuntimeScope scope,
                 UnitFileFlags flags,
index 7ec6368e1eccbc1e36f1cea920514b490aafc24b..edfae5b47be12b4fb85177c98526456535cdd4f8 100644 (file)
@@ -4812,6 +4812,42 @@ int json_dispatch_uint16(const char *name, JsonVariant *variant, JsonDispatchFla
         return 0;
 }
 
+int json_dispatch_int8(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
+        int8_t *i = ASSERT_PTR(userdata);
+        int64_t i64;
+        int r;
+
+        assert(variant);
+
+        r = json_dispatch_int64(name, variant, flags, &i64);
+        if (r < 0)
+                return r;
+
+        if (i64 < INT8_MIN || i64 > INT8_MAX)
+                return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "JSON field '%s' out of bounds.", strna(name));
+
+        *i = (int8_t) i64;
+        return 0;
+}
+
+int json_dispatch_uint8(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
+        uint8_t *u = ASSERT_PTR(userdata);
+        uint64_t u64;
+        int r;
+
+        assert(variant);
+
+        r = json_dispatch_uint64(name, variant, flags, &u64);
+        if (r < 0)
+                return r;
+
+        if (u64 > UINT8_MAX)
+                return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "JSON field '%s' out of bounds.", strna(name));
+
+        *u = (uint8_t) u64;
+        return 0;
+}
+
 int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
         char **s = ASSERT_PTR(userdata);
         int r;
index 9c8448f728b82e450de8034c1c2c7d5e18cf832c..ec6274ad8d9ec4cde7bf62aa444d43e0e18e77ea 100644 (file)
@@ -421,6 +421,8 @@ int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFla
 int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
 int json_dispatch_uint16(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
 int json_dispatch_int16(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
+int json_dispatch_int8(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
+int json_dispatch_uint8(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
 int json_dispatch_uid_gid(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
 int json_dispatch_user_group_name(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
 int json_dispatch_id128(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
index 2f2d161ca68e4d7941719f7b4c5eaaad14e68151..60e0429b82a8c12eb2b65aabde9a4529038b0ed2 100644 (file)
@@ -1,9 +1,9 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include "env-util.h"
 #include "errno-util.h"
 #include "kbd-util.h"
 #include "log.h"
-#include "nulstr-util.h"
 #include "path-util.h"
 #include "recurse-dir.h"
 #include "set.h"
 #include "strv.h"
 #include "utf8.h"
 
+#define KBD_KEYMAP_DIRS                         \
+        "/usr/share/keymaps/",                  \
+        "/usr/share/kbd/keymaps/",              \
+        "/usr/lib/kbd/keymaps/"
+
+int keymap_directories(char ***ret) {
+        assert(ret);
+
+        if (getenv_path_list("SYSTEMD_KEYMAP_DIRECTORIES", ret) >= 0)
+                return 0;
+
+        char **paths = strv_new(KBD_KEYMAP_DIRS);
+        if (!paths)
+                return log_oom_debug();
+
+        *ret = TAKE_PTR(paths);
+        return 0;
+}
+
 struct recurse_dir_userdata {
         const char *keymap_name;
         Set *keymaps;
@@ -65,16 +84,21 @@ static int keymap_recurse_dir_callback(
 
 int get_keymaps(char ***ret) {
         _cleanup_set_free_free_ Set *keymaps = NULL;
+        _cleanup_strv_free_ char **keymap_dirs = NULL;
         int r;
 
+        r = keymap_directories(&keymap_dirs);
+        if (r < 0)
+                return r;
+
         keymaps = set_new(&string_hash_ops);
         if (!keymaps)
                 return -ENOMEM;
 
-        NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
+        STRV_FOREACH(dir, keymap_dirs) {
                 r = recurse_dir_at(
                                 AT_FDCWD,
-                                dir,
+                                *dir,
                                 /* statx_mask= */ 0,
                                 /* n_depth_max= */ UINT_MAX,
                                 RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE,
@@ -85,9 +109,9 @@ int get_keymaps(char ***ret) {
                 if (r == -ENOENT)
                         continue;
                 if (ERRNO_IS_NEG_RESOURCE(r))
-                        return log_warning_errno(r, "Failed to read keymap list from %s: %m", dir);
+                        return log_warning_errno(r, "Failed to read keymap list from %s: %m", *dir);
                 if (r < 0)
-                        log_debug_errno(r, "Failed to read keymap list from %s, ignoring: %m", dir);
+                        log_debug_errno(r, "Failed to read keymap list from %s, ignoring: %m", *dir);
         }
 
         _cleanup_strv_free_ char **l = set_get_strv(keymaps);
@@ -127,15 +151,20 @@ bool keymap_is_valid(const char *name) {
 }
 
 int keymap_exists(const char *name) {
+        _cleanup_strv_free_ char **keymap_dirs = NULL;
         int r;
 
         if (!keymap_is_valid(name))
                 return -EINVAL;
 
-        NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) {
+        r = keymap_directories(&keymap_dirs);
+        if (r < 0)
+                return r;
+
+        STRV_FOREACH(dir, keymap_dirs) {
                 r = recurse_dir_at(
                                 AT_FDCWD,
-                                dir,
+                                *dir,
                                 /* statx_mask= */ 0,
                                 /* n_depth_max= */ UINT_MAX,
                                 RECURSE_DIR_IGNORE_DOT|RECURSE_DIR_ENSURE_TYPE,
@@ -148,7 +177,7 @@ int keymap_exists(const char *name) {
                 if (ERRNO_IS_NEG_RESOURCE(r))
                         return r;
                 if (r < 0 && r != -ENOENT)
-                        log_debug_errno(r, "Failed to read keymap list from %s, ignoring: %m", dir);
+                        log_debug_errno(r, "Failed to read keymap list from %s, ignoring: %m", *dir);
         }
 
         return false;
index aca0dee4bc0d2dced15050c3e967f9b77e0bf88c..a8e365e3ca43abaa4d20a00dc5535515506d4482 100644 (file)
@@ -3,11 +3,7 @@
 
 #include <stdbool.h>
 
-#define KBD_KEYMAP_DIRS                         \
-        "/usr/share/keymaps/\0"                 \
-        "/usr/share/kbd/keymaps/\0"             \
-        "/usr/lib/kbd/keymaps/\0"
-
-int get_keymaps(char ***l);
+int keymap_directories(char ***ret);
+int get_keymaps(char ***ret);
 bool keymap_is_valid(const char *name);
 int keymap_exists(const char *name);
index 81e6f1754c4f8973fb3d5cc99f0a29dbe7d151e6..2f3abe4e89438aee55975a00cef395f80352a99a 100644 (file)
@@ -140,7 +140,7 @@ static char* systemd_crypt_ra(const char *phrase, const char *setting, void **da
 int hash_password_full(const char *password, void **cd_data, int *cd_size, char **ret) {
         _cleanup_free_ char *salt = NULL;
         _cleanup_(erase_and_freep) void *_cd_data = NULL;
-        char *p;
+        const char *p;
         int r, _cd_size = 0;
 
         assert(!!cd_data == !!cd_size);
@@ -155,12 +155,7 @@ int hash_password_full(const char *password, void **cd_data, int *cd_size, char
                 return log_debug_errno(errno_or_else(SYNTHETIC_ERRNO(EINVAL)),
                                        CRYPT_RA_NAME "() failed: %m");
 
-        p = strdup(p);
-        if (!p)
-                return -ENOMEM;
-
-        *ret = p;
-        return 0;
+        return strdup_to(ret, p);
 }
 
 bool looks_like_hashed_password(const char *s) {
index f821ea7c9d693585777d6c0d46b9f47ad4af7054..df99b0b009537ca48df2126e793ac93755db2fe2 100644 (file)
@@ -5,6 +5,7 @@
 #include <sys/mount.h>
 #include <unistd.h>
 
+#include "sd-daemon.h"
 #include "sd-id128.h"
 
 #include "alloc-util.h"
@@ -12,6 +13,7 @@
 #include "creds-util.h"
 #include "fd-util.h"
 #include "id128-util.h"
+#include "initrd-util.h"
 #include "io-util.h"
 #include "log.h"
 #include "machine-id-setup.h"
@@ -141,8 +143,8 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_
         if (sd_id128_is_null(machine_id)) {
 
                 /* Try to read any existing machine ID */
-                if (id128_read_fd(fd, ID128_FORMAT_PLAIN, ret) >= 0)
-                        return 0;
+                if (id128_read_fd(fd, ID128_FORMAT_PLAIN, &machine_id) >= 0)
+                        goto finish;
 
                 /* Hmm, so, the id currently stored is not useful, then let's generate one */
                 r = generate_machine_id(root, &machine_id);
@@ -207,6 +209,9 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_
                 return r;
 
 finish:
+        if (!in_initrd())
+                (void) sd_notifyf(/* unset_environment= */ false, "X_SYSTEMD_MACHINE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(machine_id));
+
         if (ret)
                 *ret = machine_id;
 
index f56c5646c100002568c7b1fade8eb8b9a846bd9d..c9a14b4739bef8101a408403d06cd54c27c93af4 100644 (file)
@@ -32,14 +32,8 @@ int net_get_type_string(sd_device *device, uint16_t iftype, char **ret) {
 
         if (device &&
             sd_device_get_devtype(device, &t) >= 0 &&
-            !isempty(t)) {
-                p = strdup(t);
-                if (!p)
-                        return -ENOMEM;
-
-                *ret = p;
-                return 0;
-        }
+            !isempty(t))
+                return strdup_to(ret, t);
 
         t = arphrd_to_name(iftype);
         if (!t)
index 87e7d285c534d78f6cb3f8d7cb238fba6a9b56ba..e070f9636c66cd54f8f589c6529efd30b71a1d3c 100644 (file)
@@ -101,7 +101,6 @@ int suggest_passwords(void) {
         _cleanup_strv_free_erase_ char **suggestions = NULL;
         _cleanup_(erase_and_freep) char *joined = NULL;
         char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
-        size_t i;
         int r;
 
         r = pwq_allocate_context(&pwq);
@@ -115,7 +114,7 @@ int suggest_passwords(void) {
         if (!suggestions)
                 return log_oom();
 
-        for (i = 0; i < N_SUGGESTIONS; i++) {
+        for (size_t i = 0; i < N_SUGGESTIONS; i++) {
                 r = sym_pwquality_generate(pwq, 64, suggestions + i);
                 if (r < 0)
                         return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to generate password, ignoring: %s",
@@ -145,13 +144,10 @@ int check_password_quality(const char *password, const char *old, const char *us
         r = sym_pwquality_check(pwq, password, old, username, &auxerror);
         if (r < 0) {
                 if (ret_error) {
-                        _cleanup_free_ char *e = NULL;
-
-                        e = strdup(sym_pwquality_strerror(buf, sizeof(buf), r, auxerror));
-                        if (!e)
-                                return -ENOMEM;
-
-                        *ret_error = TAKE_PTR(e);
+                        r = strdup_to(ret_error,
+                                      sym_pwquality_strerror(buf, sizeof(buf), r, auxerror));
+                        if (r < 0)
+                                return r;
                 }
 
                 return 0; /* all bad */
index c551ed62e3d59e58b267c1a8d0b976333083e808..85c599c5c657493b91d869f01de120d56936624d 100644 (file)
@@ -141,16 +141,8 @@ int terminal_urlify_path(const char *path, const char *text, char **ret) {
         if (isempty(text))
                 text = path;
 
-        if (!urlify_enabled()) {
-                char *n;
-
-                n = strdup(text);
-                if (!n)
-                        return -ENOMEM;
-
-                *ret = n;
-                return 0;
-        }
+        if (!urlify_enabled())
+                return strdup_to(ret, text);
 
         r = file_url_from_path(path, &url);
         if (r < 0)
index a514428ef2c75d6f484aaa0a0569c956102880de..bdbd79087ca27238f0ec412d20d83342b4983c0d 100644 (file)
@@ -266,7 +266,7 @@ static int insert_string(PTYForward *f, size_t offset, const char *s) {
         return (int) l;
 }
 
-static int insert_newline_color_erase(PTYForward *f, size_t offset) {
+static int insert_background_color(PTYForward *f, size_t offset) {
         _cleanup_free_ char *s = NULL;
 
         assert(f);
@@ -274,29 +274,6 @@ static int insert_newline_color_erase(PTYForward *f, size_t offset) {
         if (!f->background_color)
                 return 0;
 
-        /* When we see a newline (ASCII 10) then this sets the background color to the desired one, and erase the rest
-         * of the line with it */
-
-        s = background_color_sequence(f);
-        if (!s)
-                return -ENOMEM;
-
-        if (!strextend(&s, ANSI_ERASE_TO_END_OF_LINE))
-                return -ENOMEM;
-
-        return insert_string(f, offset, s);
-}
-
-static int insert_carriage_return_color(PTYForward *f, size_t offset) {
-        _cleanup_free_ char *s = NULL;
-
-        assert(f);
-
-        if (!f->background_color)
-                return 0;
-
-        /* When we see a carriage return (ASCII 13) then this sets only the background */
-
         s = background_color_sequence(f);
         if (!s)
                 return -ENOMEM;
@@ -430,29 +407,19 @@ static int pty_forward_ansi_process(PTYForward *f, size_t offset) {
                 case ANSI_COLOR_STATE_TEXT:
                         break;
 
-                case ANSI_COLOR_STATE_NEWLINE: {
-                        /* Immediately after a newline insert an ANSI sequence to erase the line with a background color */
-
-                        r = insert_newline_color_erase(f, i);
-                        if (r < 0)
-                                return r;
-
-                        i += r;
-                        break;
-                }
-
-                case ANSI_COLOR_STATE_CARRIAGE_RETURN: {
-                        /* Immediately after a carriage return insert an ANSI sequence set the background color back */
+                case ANSI_COLOR_STATE_NEWLINE:
+                case ANSI_COLOR_STATE_CARRIAGE_RETURN:
+                        /* Immediately after a newline (ASCII 10) or carriage return (ASCII 13) insert an
+                         * ANSI sequence set the background color back. */
 
-                        r = insert_carriage_return_color(f, i);
+                        r = insert_background_color(f, i);
                         if (r < 0)
                                 return r;
 
                         i += r;
                         break;
-                }
 
-                case ANSI_COLOR_STATE_ESC: {
+                case ANSI_COLOR_STATE_ESC:
 
                         if (c == '[') {
                                 f->ansi_color_state = ANSI_COLOR_STATE_CSI_SEQUENCE;
@@ -461,11 +428,9 @@ static int pty_forward_ansi_process(PTYForward *f, size_t offset) {
                                 f->ansi_color_state = ANSI_COLOR_STATE_OSC_SEQUENCE;
                                 continue;
                         }
-
                         break;
-                }
 
-                case ANSI_COLOR_STATE_CSI_SEQUENCE: {
+                case ANSI_COLOR_STATE_CSI_SEQUENCE:
 
                         if (c >= 0x20 && c <= 0x3F) {
                                 /* If this is a "parameter" or "intermediary" byte (i.e. ranges 0x20…0x2F and
@@ -493,11 +458,9 @@ static int pty_forward_ansi_process(PTYForward *f, size_t offset) {
                                 f->csi_sequence = mfree(f->csi_sequence);
                                 f->ansi_color_state = ANSI_COLOR_STATE_TEXT;
                         }
-
                         continue;
-                }
 
-                case ANSI_COLOR_STATE_OSC_SEQUENCE: {
+                case ANSI_COLOR_STATE_OSC_SEQUENCE:
 
                         if ((uint8_t) c >= ' ') {
                                 if (strlen_ptr(f->osc_sequence) >= 64) {
@@ -526,9 +489,7 @@ static int pty_forward_ansi_process(PTYForward *f, size_t offset) {
                                 f->osc_sequence = mfree(f->osc_sequence);
                                 f->ansi_color_state = ANSI_COLOR_STATE_TEXT;
                         }
-
                         continue;
-                }
 
                 default:
                         assert_not_reached();
index a56b8365fb4bd9569683c3d7576e235ec30c9df4..f6739f2c662a066610aa756ab1580d8fa4bb5157 100644 (file)
@@ -111,18 +111,7 @@ int specifier_printf(const char *text, size_t max_length, const Specifier table[
 /* Generic handler for simple string replacements */
 
 int specifier_string(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
-        char *n = NULL;
-
-        assert(ret);
-
-        if (!isempty(data)) {
-                n = strdup(data);
-                if (!n)
-                        return -ENOMEM;
-        }
-
-        *ret = n;
-        return 0;
+        return strdup_to(ASSERT_PTR(ret), empty_to_null(data));
 }
 
 int specifier_real_path(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
@@ -249,32 +238,18 @@ int specifier_pretty_hostname(char specifier, const void *data, const char *root
 
 int specifier_kernel_release(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
         struct utsname uts;
-        char *n;
 
         assert(ret);
 
         if (uname(&uts) < 0)
                 return -errno;
 
-        n = strdup(uts.release);
-        if (!n)
-                return -ENOMEM;
-
-        *ret = n;
-        return 0;
+        return strdup_to(ret, uts.release);
 }
 
 int specifier_architecture(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
-        char *t;
-
-        assert(ret);
-
-        t = strdup(architecture_to_string(uname_architecture()));
-        if (!t)
-                return -ENOMEM;
-
-        *ret = t;
-        return 0;
+        return strdup_to(ASSERT_PTR(ret),
+                         architecture_to_string(uname_architecture()));
 }
 
 /* Note: fields in /etc/os-release might quite possibly be missing, even if everything is entirely valid
@@ -420,7 +395,6 @@ int specifier_user_shell(char specifier, const void *data, const char *root, con
 
 int specifier_tmp_dir(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
         const char *p;
-        char *copy;
         int r;
 
         assert(ret);
@@ -432,17 +406,12 @@ int specifier_tmp_dir(char specifier, const void *data, const char *root, const
                 if (r < 0)
                         return r;
         }
-        copy = strdup(p);
-        if (!copy)
-                return -ENOMEM;
 
-        *ret = copy;
-        return 0;
+        return strdup_to(ret, p);
 }
 
 int specifier_var_tmp_dir(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
         const char *p;
-        char *copy;
         int r;
 
         assert(ret);
@@ -454,12 +423,8 @@ int specifier_var_tmp_dir(char specifier, const void *data, const char *root, co
                 if (r < 0)
                         return r;
         }
-        copy = strdup(p);
-        if (!copy)
-                return -ENOMEM;
 
-        *ret = copy;
-        return 0;
+        return strdup_to(ret, p);
 }
 
 int specifier_escape_strv(char **l, char ***ret) {
index 9c7d24c0d6de107d0205006c840c16db4aa9fe9b..85f9463f9b5c5f1a2bcc69c4e6d8eabe4c2244a7 100644 (file)
@@ -200,3 +200,153 @@ static inline int run_test_table(void) {
         DEFINE_TEST_MAIN_FULL(log_level, intro, NULL)
 #define DEFINE_TEST_MAIN(log_level)                     \
         DEFINE_TEST_MAIN_FULL(log_level, NULL, NULL)
+
+#define ASSERT_OK(expr)                                                                                         \
+        ({                                                                                                      \
+                typeof(expr) _result = (expr);                                                                  \
+                if (_result < 0) {                                                                              \
+                        log_error_errno(_result, "%s:%i: Assertion failed: %s: %m",                             \
+                                        PROJECT_FILE, __LINE__, #expr);                                         \
+                        abort();                                                                                \
+                }                                                                                               \
+         })
+
+#define ASSERT_TRUE(expr)                                                                                       \
+        ({                                                                                                      \
+                if (!(expr)) {                                                                                  \
+                        log_error("%s:%i: Assertion failed: expected \"%s\" to be true",                        \
+                                  PROJECT_FILE, __LINE__, #expr);                                               \
+                        abort();                                                                                \
+                }                                                                                               \
+        })
+
+#define ASSERT_FALSE(expr)                                                                                      \
+        ({                                                                                                      \
+                if ((expr)) {                                                                                   \
+                        log_error("%s:%i: Assertion failed: expected \"%s\" to be false",                       \
+                                  PROJECT_FILE, __LINE__, #expr);                                               \
+                        abort();                                                                                \
+                }                                                                                               \
+        })
+
+#define ASSERT_NULL(expr)                                                                                       \
+        ({                                                                                                      \
+                if ((expr) != NULL) {                                                                           \
+                        log_error("%s:%i: Assertion failed: expected \"%s\" to be NULL",                        \
+                                  PROJECT_FILE, __LINE__, #expr);                                               \
+                        abort();                                                                                \
+                }                                                                                               \
+        })
+
+#define ASSERT_NOT_NULL(expr)                                                                                   \
+        ({                                                                                                      \
+                if ((expr) == NULL) {                                                                           \
+                        log_error("%s:%i: Assertion failed: expected \"%s\" to be not NULL",                    \
+                                  PROJECT_FILE, __LINE__, #expr);                                               \
+                        abort();                                                                                \
+                }                                                                                               \
+        })
+
+#define ASSERT_STREQ(expr1, expr2)                                                                              \
+        ({                                                                                                      \
+                const char* _expr1 = (expr1);                                                                   \
+                const char* _expr2 = (expr2);                                                                   \
+                if (strcmp(_expr1, _expr2) != 0) {                                                              \
+                        log_error("%s:%i: Assertion failed: expected \"%s == %s\", but \"%s != %s\"",           \
+                                  PROJECT_FILE, __LINE__, #expr1, #expr2, _expr1, _expr2);                      \
+                        abort();                                                                                \
+                }                                                                                               \
+        })
+
+/* DECIMAL_STR_FMT() uses _Generic which cannot be used in string concatenation so we have to format the
+ * input into strings first and then format those into the final assertion message. */
+
+#define ASSERT_EQ(expr1, expr2)                                                                                 \
+        ({                                                                                                      \
+                typeof(expr1) _expr1 = (expr1);                                                                 \
+                typeof(expr2) _expr2 = (expr2);                                                                 \
+                if (_expr1 != _expr2) {                                                                         \
+                        char _sexpr1[DECIMAL_STR_MAX(typeof(expr1))];                                           \
+                        char _sexpr2[DECIMAL_STR_MAX(typeof(expr2))];                                           \
+                        xsprintf(_sexpr1, DECIMAL_STR_FMT(_expr1), _expr1);                                     \
+                        xsprintf(_sexpr2, DECIMAL_STR_FMT(_expr2), _expr2);                                     \
+                        log_error("%s:%i: Assertion failed: expected \"%s == %s\", but \"%s != %s\"",           \
+                                  PROJECT_FILE, __LINE__, #expr1, #expr2, _sexpr1, _sexpr2);                    \
+                        abort();                                                                                \
+                }                                                                                               \
+        })
+
+#define ASSERT_GE(expr1, expr2)                                                                                 \
+        ({                                                                                                      \
+                typeof(expr1) _expr1 = (expr1);                                                                 \
+                typeof(expr2) _expr2 = (expr2);                                                                 \
+                if (_expr1 < _expr2) {                                                                          \
+                        char _sexpr1[DECIMAL_STR_MAX(typeof(expr1))];                                           \
+                        char _sexpr2[DECIMAL_STR_MAX(typeof(expr2))];                                           \
+                        xsprintf(_sexpr1, DECIMAL_STR_FMT(_expr1), _expr1);                                     \
+                        xsprintf(_sexpr2, DECIMAL_STR_FMT(_expr2), _expr2);                                     \
+                        log_error("%s:%i: Assertion failed: expected \"%s >= %s\", but \"%s < %s\"",            \
+                                  PROJECT_FILE, __LINE__, #expr1, #expr2, _sexpr1, _sexpr2);                    \
+                        abort();                                                                                \
+                }                                                                                               \
+        })
+
+#define ASSERT_LE(expr1, expr2)                                                                                 \
+        ({                                                                                                      \
+                typeof(expr1) _expr1 = (expr1);                                                                 \
+                typeof(expr2) _expr2 = (expr2);                                                                 \
+                if (_expr1 > _expr2) {                                                                          \
+                        char _sexpr1[DECIMAL_STR_MAX(typeof(expr1))];                                           \
+                        char _sexpr2[DECIMAL_STR_MAX(typeof(expr2))];                                           \
+                        xsprintf(_sexpr1, DECIMAL_STR_FMT(_expr1), _expr1);                                     \
+                        xsprintf(_sexpr2, DECIMAL_STR_FMT(_expr2), _expr2);                                     \
+                        log_error("%s:%i: Assertion failed: expected \"%s <= %s\", but \"%s > %s\"",            \
+                                  PROJECT_FILE, __LINE__, #expr1, #expr2, _sexpr1, _sexpr2);                    \
+                        abort();                                                                                \
+                }                                                                                               \
+        })
+
+#define ASSERT_NE(expr1, expr2)                                                                                 \
+        ({                                                                                                      \
+                typeof(expr1) _expr1 = (expr1);                                                                 \
+                typeof(expr2) _expr2 = (expr2);                                                                 \
+                if (_expr1 == _expr2) {                                                                         \
+                        char _sexpr1[DECIMAL_STR_MAX(typeof(expr1))];                                           \
+                        char _sexpr2[DECIMAL_STR_MAX(typeof(expr2))];                                           \
+                        xsprintf(_sexpr1, DECIMAL_STR_FMT(_expr1), _expr1);                                     \
+                        xsprintf(_sexpr2, DECIMAL_STR_FMT(_expr2), _expr2);                                     \
+                        log_error("%s:%i: Assertion failed: expected \"%s != %s\", but \"%s == %s\"",           \
+                                  PROJECT_FILE, __LINE__, #expr1, #expr2, _sexpr1, _sexpr2);                    \
+                        abort();                                                                                \
+                }                                                                                               \
+        })
+
+#define ASSERT_GT(expr1, expr2)                                                                                 \
+        ({                                                                                                      \
+                typeof(expr1) _expr1 = (expr1);                                                                 \
+                typeof(expr2) _expr2 = (expr2);                                                                 \
+                if (!(_expr1 > _expr2)) {                                                                       \
+                        char _sexpr1[DECIMAL_STR_MAX(typeof(expr1))];                                           \
+                        char _sexpr2[DECIMAL_STR_MAX(typeof(expr2))];                                           \
+                        xsprintf(_sexpr1, DECIMAL_STR_FMT(_expr1), _expr1);                                     \
+                        xsprintf(_sexpr2, DECIMAL_STR_FMT(_expr2), _expr2);                                     \
+                        log_error("%s:%i: Assertion failed: expected \"%s > %s\", but \"%s <= %s\"",            \
+                                  PROJECT_FILE, __LINE__, #expr1, #expr2, _sexpr1, _sexpr2);                    \
+                        abort();                                                                                \
+                }                                                                                               \
+        })
+
+#define ASSERT_LT(expr1, expr2)                                                                                 \
+        ({                                                                                                      \
+                typeof(expr1) _expr1 = (expr1);                                                                 \
+                typeof(expr2) _expr2 = (expr2);                                                                 \
+                if (!(_expr1 < _expr2)) {                                                                       \
+                        char _sexpr1[DECIMAL_STR_MAX(typeof(expr1))];                                           \
+                        char _sexpr2[DECIMAL_STR_MAX(typeof(expr2))];                                           \
+                        xsprintf(_sexpr1, DECIMAL_STR_FMT(_expr1), _expr1);                                     \
+                        xsprintf(_sexpr2, DECIMAL_STR_FMT(_expr2), _expr2);                                     \
+                        log_error("%s:%i: Assertion failed: expected \"%s < %s\", but \"%s >= %s\"",            \
+                                  PROJECT_FILE, __LINE__, #expr1, #expr2, _sexpr1, _sexpr2);                    \
+                        abort();                                                                                \
+                }                                                                                               \
+        })
index 6c107c53fa88dbd6055e945a45255d0a0c0b2a03..d4072ec398281508392fd0b31905f835a72cff8a 100644 (file)
@@ -3377,7 +3377,7 @@ int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret)
         }
 
         _cleanup_free_ char *desc = NULL;
-        if (asprintf(&desc, "%s-%i", server->description ?: "varlink", v->fd) >= 0)
+        if (asprintf(&desc, "%s-%i", varlink_server_description(server), v->fd) >= 0)
                 v->description = TAKE_PTR(desc);
 
         /* Link up the server and the connection, and take reference in both directions. Note that the
index 08532690a9c7581e56c35b47b5646df942c2330b..5e037835435501060e8292b01b11ffa984e64800 100644 (file)
@@ -108,8 +108,9 @@ static int make_sshd_template_unit(
                         "Description=OpenSSH Per-Connection Server Daemon\n"
                         "Documentation=man:systemd-ssh-generator(8) man:sshd(8)\n"
                         "[Service]\n"
-                        "ExecStart=-%s -i\n"
-                        "StandardInput=socket",
+                        "ExecStart=-%s -i -o \"AuthorizedKeysFile ${CREDENTIALS_DIRECTORY}/ssh.ephemeral-authorized_keys-all .ssh/authorized_keys\"\n"
+                        "StandardInput=socket\n"
+                        "ImportCredential=ssh.ephemeral-authorized_keys-all",
                         sshd_binary);
 
                 r = fflush_and_check(f);
@@ -128,7 +129,8 @@ static int write_socket_unit(
                 const char *dest,
                 const char *unit,
                 const char *listen_stream,
-                const char *comment) {
+                const char *comment,
+                bool with_ssh_access_target_dependency) {
 
         int r;
 
@@ -149,13 +151,21 @@ static int write_socket_unit(
         fprintf(f,
                 "[Unit]\n"
                 "Description=OpenSSH Server Socket (systemd-ssh-generator, %s)\n"
-                "Documentation=man:systemd-ssh-generator(8)\n"
+                "Documentation=man:systemd-ssh-generator(8)\n",
+                comment);
+
+        /* When this is a remotely accessible socket let's mark this with a milestone: ssh-access.target */
+        if (with_ssh_access_target_dependency)
+                fputs("Wants=ssh-access.target\n"
+                      "Before=ssh-access.target\n",
+                      f);
+
+        fprintf(f,
                 "\n[Socket]\n"
                 "ListenStream=%s\n"
                 "Accept=yes\n"
                 "PollLimitIntervalSec=30s\n"
                 "PollLimitBurst=50\n",
-                comment,
                 listen_stream);
 
         r = fflush_and_check(f);
@@ -230,7 +240,8 @@ static int add_vsock_socket(
                         dest,
                         "sshd-vsock.socket",
                         "vsock::22",
-                        "AF_VSOCK");
+                        "AF_VSOCK",
+                        /* with_ssh_access_target_dependency= */ true);
         if (r < 0)
                 return r;
 
@@ -264,7 +275,8 @@ static int add_local_unix_socket(
                         dest,
                         "sshd-unix-local.socket",
                         "/run/ssh-unix-local/socket",
-                        "AF_UNIX Local");
+                        "AF_UNIX Local",
+                        /* with_ssh_access_target_dependency= */ false);
         if (r < 0)
                 return r;
 
@@ -320,7 +332,8 @@ static int add_export_unix_socket(
                         dest,
                         "sshd-unix-export.socket",
                         "/run/host/unix-export/ssh",
-                        "AF_UNIX Export");
+                        "AF_UNIX Export",
+                        /* with_ssh_access_target_dependency= */ true);
         if (r < 0)
                 return r;
 
@@ -370,7 +383,8 @@ static int add_extra_sockets(
                                 dest,
                                 socket ?: "sshd-extra.socket",
                                 *i,
-                                *i);
+                                *i,
+                                /* with_ssh_access_target_dependency= */ true);
                 if (r < 0)
                         return r;
 
index d50edb413fcb6fedae536236bacb14e8755023cf..a91d7064bbef970cb2bbf776f683ec3ff92777f3 100644 (file)
@@ -62,30 +62,29 @@ opts = [['c'],
         ['c', '-std=iso9899:1990'],
         ['c', '-std=iso9899:2011']]
 
-if cc.has_argument('-std=iso9899:2017')
-        opts += [['c', '-std=iso9899:2017']]
-endif
-
-if cc.has_argument('-std=c2x')
-        opts += [['c', '-std=c2x']]
-endif
+foreach opt : ['-std=iso9899:2017',
+               '-std=c23',
+              ]
+        if cc.has_argument(opt)
+                opts += [['c', opt]]
+        endif
+endforeach
 
 if cxx_cmd != ''
         opts += [['c++'],
                  ['c++', '-std=c++98'],
                  ['c++', '-std=c++11']]
-        if cxx.has_argument('-std=c++14')
-                opts += [['c++', '-std=c++14']]
-        endif
-        if cxx.has_argument('-std=c++17')
-                opts += [['c++', '-std=c++17']]
-        endif
-        if cxx.has_argument('-std=c++20')
-                opts += [['c++', '-std=c++20']]
-        endif
-        if cxx.has_argument('-std=c++23')
-                opts += [['c++', '-std=c++23']]
-        endif
+
+        foreach opt : ['-std=c++14',
+                       '-std=c++17',
+                       '-std=c++20',
+                       '-std=c++23',
+                       '-std=c++26',
+                      ]
+                if cxx.has_argument(opt)
+                        opts += [['c++', opt]]
+                endif
+        endforeach
 endif
 
 foreach header : _systemd_headers + _not_installed_headers + [libudev_h_path]
index 486af48b25175a97512307d2afdffb03b5d1b99c..1bba7a6077089d81d9a909721c4f6b8d9645413a 100644 (file)
@@ -81,7 +81,7 @@ int sd_dhcp_server_set_smtp(sd_dhcp_server *server, const struct in_addr smtp[],
 int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v);
 int sd_dhcp_server_add_vendor_option(sd_dhcp_server *server, sd_dhcp_option *v);
 int sd_dhcp_server_set_static_lease(sd_dhcp_server *server, const struct in_addr *address, uint8_t *client_id, size_t client_id_size);
-int sd_dhcp_server_set_lease_file(sd_dhcp_server *server, const char *path);
+int sd_dhcp_server_set_lease_file(sd_dhcp_server *server, int dir_fd, const char *path);
 
 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint64_t t);
 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint64_t t);
index e4a67f048b8524111d3e1274d96a81844b8d8903..7434051ce1fb92a1d8b7aea760d50a63d3c0d5b3 100644 (file)
@@ -57,6 +57,7 @@ int sd_journal_perror_with_location(const char *file, const char *line, const ch
 #endif
 
 int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix);
+int sd_journal_stream_fd_with_namespace(const char *name_space, const char *identifier, int priority, int level_prefix);
 
 /* Browse journal stream */
 
index e9e94637909a3b8926e9273da7424d0a74ee08e7..571d966ca0049b7c49cfd493444b0ec672790902 100644 (file)
@@ -74,6 +74,7 @@ simple_tests += files(
         'test-dev-setup.c',
         'test-device-nodes.c',
         'test-devnum-util.c',
+        'test-dirent-util.c',
         'test-dns-domain.c',
         'test-ellipsize.c',
         'test-env-file.c',
@@ -112,6 +113,7 @@ simple_tests += files(
         'test-iovec-util.c',
         'test-journal-importer.c',
         'test-kbd-util.c',
+        'test-label.c',
         'test-limits-util.c',
         'test-list.c',
         'test-local-addresses.c',
@@ -146,6 +148,7 @@ simple_tests += files(
         'test-psi-util.c',
         'test-ratelimit.c',
         'test-raw-clone.c',
+        'test-recovery-key.c',
         'test-recurse-dir.c',
         'test-replace-var.c',
         'test-rlimit-util.c',
index cb5a981dc3c0871fa528dc0d2a52c8fd0226bf45..4e7805b40a5db2f275a8b72792390d501437bf68 100644 (file)
@@ -328,12 +328,13 @@ TEST(shift_path) {
 
 TEST(mask_supported, .sd_booted = true) {
         CGroupMask m;
-        CGroupController c;
 
         assert_se(cg_mask_supported(&m) >= 0);
 
-        for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++)
-                printf("'%s' is supported: %s\n", cgroup_controller_to_string(c), yes_no(m & CGROUP_CONTROLLER_TO_MASK(c)));
+        for (CGroupController c = 0; c < _CGROUP_CONTROLLER_MAX; c++)
+                printf("'%s' is supported: %s\n",
+                       cgroup_controller_to_string(c),
+                       yes_no(m & CGROUP_CONTROLLER_TO_MASK(c)));
 }
 
 TEST(is_cgroup_fs, .sd_booted = true) {
@@ -392,7 +393,7 @@ TEST(cg_tests) {
 TEST(cg_get_keyed_attribute) {
         _cleanup_free_ char *val = NULL;
         char *vals3[3] = {}, *vals3a[3] = {};
-        int i, r;
+        int r;
 
         r = cg_get_keyed_attribute("cpu", "/init.scope", "no_such_file", STRV_MAKE("no_such_attr"), &val);
         if (IN_SET(r, -ENOMEDIUM, -ENOENT) || ERRNO_IS_PRIVILEGE(r)) {
@@ -430,7 +431,7 @@ TEST(cg_get_keyed_attribute) {
 
         assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat",
                                          STRV_MAKE("usage_usec", "user_usec", "system_usec"), vals3) == 0);
-        for (i = 0; i < 3; i++)
+        for (size_t i = 0; i < 3; i++)
                 free(vals3[i]);
 
         assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat",
@@ -440,7 +441,7 @@ TEST(cg_get_keyed_attribute) {
 
         assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat",
                                          STRV_MAKE("system_usec", "user_usec", "usage_usec"), vals3a) == 0);
-        for (i = 0; i < 3; i++)
+        for (size_t i = 0; i < 3; i++)
                 free(vals3a[i]);
 
         assert_se(cg_get_keyed_attribute_graceful("cpu", "/init.scope", "cpu.stat",
@@ -448,7 +449,7 @@ TEST(cg_get_keyed_attribute) {
         log_info("cpu /init.scope cpu.stat [system_usec user_usec usage_usec] → \"%s\", \"%s\", \"%s\"",
                  vals3a[0], vals3a[1], vals3a[2]);
 
-        for (i = 0; i < 3; i++) {
+        for (size_t i = 0; i < 3; i++) {
                 free(vals3[i]);
                 free(vals3a[i]);
         }
index 57cd77d4e506ec2aa471f79a3d0216f4b234fd24..868b862dc7acda93f7cda0974399c0136ac9a9d0 100644 (file)
@@ -188,13 +188,13 @@ _unused_ static void test_compress_stream(const char *compression,
 
         log_debug("/* create source from %s */", srcfile);
 
-        assert_se((src = open(srcfile, O_RDONLY|O_CLOEXEC)) >= 0);
+        ASSERT_OK((src = open(srcfile, O_RDONLY|O_CLOEXEC)));
 
         log_debug("/* test compression */");
 
         assert_se((dst = mkostemp_safe(pattern)) >= 0);
 
-        assert_se(compress(src, dst, -1, &uncompressed_size) >= 0);
+        ASSERT_OK(compress(src, dst, -1, &uncompressed_size));
 
         if (cat) {
                 assert_se(asprintf(&cmd, "%s %s | diff %s -", cat, pattern, srcfile) > 0);
diff --git a/src/test/test-dirent-util.c b/src/test/test-dirent-util.c
new file mode 100644 (file)
index 0000000..f981697
--- /dev/null
@@ -0,0 +1,213 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include "alloc-util.h"
+#include "dirent-util.h"
+#include "fs-util.h"
+#include "mkdir.h"
+#include "path-util.h"
+#include "rm-rf.h"
+#include "stat-util.h"
+#include "string-util.h"
+#include "tmpfile-util.h"
+#include "tests.h"
+
+TEST (test_dirent_ensure_type) {
+        int r, dir_fd;
+        static struct dirent de = {
+                .d_type = DT_UNKNOWN,
+                .d_name = "test",
+        };
+
+        assert_se(de.d_type == DT_UNKNOWN);
+
+        dir_fd = 0;
+        dirent_ensure_type(dir_fd, &de);
+
+        /* Test when d_name is "." or ".." */
+        strcpy(de.d_name, ".");
+        r = dirent_ensure_type(dir_fd, &de);
+        assert_se(r == 0);
+        assert_se(de.d_type == DT_DIR);
+
+        strcpy(de.d_name, "..");
+        r = dirent_ensure_type(dir_fd, &de);
+        assert_se(r == 0);
+        assert_se(de.d_type == DT_DIR);
+}
+
+TEST (test_dirent_is_file) {
+        _cleanup_(rm_rf_physical_and_freep) char *t = NULL;
+        const char *name, *dotfile, *name_alias, *bakfile, *tilda;
+        const struct dirent *de_reg, *de_lnk, *de_dot, *de_bak, *de_tilda;
+        DIR *dir;
+
+        static const struct dirent de_unknown = {
+                .d_type = DT_UNKNOWN,
+                .d_name = "test_unknown",
+        };
+
+        assert_se(mkdtemp_malloc(NULL, &t) >= 0);
+
+        name = strjoina(t, "/test.txt");
+        dotfile = strjoina(t, "/.hidden_file");
+        bakfile = strjoina(t, "/test.bak");
+        tilda = strjoina(t, "/test~");
+        name_alias = strjoina(t, "/test_link");
+
+        assert_se(touch(name) >= 0);
+        assert_se(touch(dotfile) >= 0);
+        assert_se(touch(bakfile) >= 0);
+        assert_se(touch(tilda) >= 0);
+
+        if (symlink(name, name_alias) < 0) {
+                assert_se(IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM));
+                log_tests_skipped_errno(errno, "symlink() not possible");
+        }
+
+        dir = opendir(t);
+        if (dir == NULL) {
+                log_error_errno(errno, "Failed to open directory '%s': %m", t);
+                exit(EXIT_FAILURE);
+        }
+
+        rewinddir(dir);
+        while ((de_reg = readdir_ensure_type(dir)) != NULL)
+                if (strcmp(de_reg->d_name, "test.txt") == 0)
+                        break;
+
+        rewinddir(dir);
+        while ((de_lnk = readdir_ensure_type(dir)) != NULL)
+                if (strcmp(de_lnk->d_name, "test_link") == 0)
+                        break;
+
+        rewinddir(dir);
+        while ((de_dot = readdir_ensure_type(dir)) != NULL)
+                if (strcmp(de_dot->d_name, ".hidden_file") == 0)
+                        break;
+
+        rewinddir(dir);
+        while ((de_bak = readdir(dir)) != NULL)
+                if (strcmp(de_bak->d_name, "test.bak") == 0)
+                        break;
+
+        rewinddir(dir);
+        while ((de_tilda = readdir(dir)) != NULL)
+                if (strcmp(de_tilda->d_name, "test~") == 0)
+                        break;
+
+        /* Test when d_type is DT_REG, DT_LNK, or DT_UNKNOWN */
+        assert_se(dirent_is_file(de_reg) == true);
+        if (de_lnk)
+                assert_se(dirent_is_file(de_lnk) == true);
+        else
+                log_tests_skipped("de_lnk is NULL, skipping test");
+        assert_se(dirent_is_file(&de_unknown) == true);
+
+        /* Test for hidden files */
+        assert_se(dirent_is_file(de_dot) == false);
+        assert_se(dirent_is_file(de_bak) == false);
+        assert_se(dirent_is_file(de_tilda) == false);
+
+        closedir(dir);
+}
+
+TEST (test_dirent_is_file_with_suffix) {
+        _cleanup_(rm_rf_physical_and_freep) char *t = NULL;
+        const char *name, *dotfile, *name_alias, *dotdot, *chr;
+        const struct dirent *de_reg, *de_lnk, *de_dot, *de_dotdot, *de_chr;
+        DIR *dir;
+
+        static const struct dirent de_unknown = {
+                .d_type = DT_UNKNOWN,
+                .d_name = "test_unknown",
+        };
+
+        assert_se(mkdtemp_malloc(NULL, &t) >= 0);
+
+        name = strjoina(t, "/test.txt");
+        dotfile = strjoina(t, "/.hidden_file");
+        dotdot = strjoina(t, "/..dotdot");
+        chr = strjoina(t, "/test_chr");
+        name_alias = strjoina(t, "/test_link");
+
+        assert_se(touch(name) >= 0);
+        assert_se(touch(dotfile) >= 0);
+        assert_se(touch(dotdot) >= 0);
+        assert_se(mknod(chr, 0775 | S_IFCHR, makedev(0, 0)) >= 0);
+
+        if (symlink(name, name_alias) < 0) {
+                assert_se(IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM));
+                log_tests_skipped_errno(errno, "symlink() not possible");
+        }
+
+        dir = opendir(t);
+        if (dir == NULL) {
+                log_error_errno(errno, "Failed to open directory '%s': %m", t);
+                exit(EXIT_FAILURE);
+        }
+
+        rewinddir(dir);
+        while ((de_reg = readdir_ensure_type(dir)) != NULL)
+                if (strcmp(de_reg->d_name, "test.txt") == 0)
+                        break;
+
+        rewinddir(dir);
+        while ((de_lnk = readdir_ensure_type(dir)) != NULL)
+                if (strcmp(de_lnk->d_name, "test_link") == 0)
+                        break;
+
+        rewinddir(dir);
+        while ((de_dot = readdir_ensure_type(dir)) != NULL)
+                if (strcmp(de_dot->d_name, ".hidden_file") == 0)
+                        break;
+
+        rewinddir(dir);
+        while ((de_dotdot = readdir(dir)) != NULL)
+                if (strcmp(de_dotdot->d_name, "..dotdot") == 0)
+                        break;
+
+        rewinddir(dir);
+        while ((de_chr = readdir(dir)) != NULL)
+                if (strcmp(de_chr->d_name, "test_chr") == 0)
+                        break;
+
+        /* Test when d_type is not DT_REG, DT_LNK, or DT_UNKNOWN */
+        assert_se(!dirent_is_file_with_suffix(de_chr, NULL));
+
+        /* Test when suffix is NULL */
+        assert_se(dirent_is_file_with_suffix(de_reg, NULL) == true);
+        if (de_lnk)
+                assert_se(dirent_is_file_with_suffix(de_lnk, NULL) == true);
+        else
+                log_tests_skipped("de_lnk is NULL, skipping test");
+        assert_se(dirent_is_file_with_suffix(&de_unknown, NULL) == true);
+
+        /* Test for present suffix */
+        assert_se(dirent_is_file_with_suffix(de_reg, "txt") == true);
+        if (de_lnk)
+                assert_se(dirent_is_file_with_suffix(de_lnk, "link") == true);
+        else
+                log_tests_skipped("de_lnk is NULL, skipping test");
+        assert_se(dirent_is_file_with_suffix(&de_unknown, "unknown") == true);
+
+        /* Test for absent suffix */
+        assert_se(dirent_is_file_with_suffix(de_reg, "svg") == false);
+        if (de_lnk)
+                assert_se(dirent_is_file_with_suffix(de_lnk, "pdf") == false);
+        else
+                log_tests_skipped("de_lnk is NULL, skipping test");
+        assert_se(dirent_is_file_with_suffix(&de_unknown, "yes") == false);
+
+        /* Test for dot and dot-dot */
+        assert_se(dirent_is_file_with_suffix(de_dot, NULL) == false);
+        assert_se(dirent_is_file_with_suffix(de_dotdot, NULL) == false);
+
+        closedir(dir);
+}
+
+DEFINE_TEST_MAIN(LOG_INFO);
index b32feffd30333f19f3c2ad3cdd7af0316d6b8b88..b27c79fdc93d1ac8ae69ed22abb05e10d1bd6428 100644 (file)
@@ -753,6 +753,36 @@ TEST(xopenat_lock_full) {
         assert_se(xopenat_lock_full(tfd, "def", O_DIRECTORY, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
 }
 
+TEST(linkat_replace) {
+        _cleanup_(rm_rf_physical_and_freep) char *t = NULL;
+        _cleanup_close_ int tfd = -EBADF;
+
+        assert_se((tfd = mkdtemp_open(NULL, 0, &t)) >= 0);
+
+        _cleanup_close_ int fd1 = openat(tfd, "foo", O_CREAT|O_RDWR|O_CLOEXEC, 0600);
+        assert_se(fd1 >= 0);
+
+        assert_se(linkat_replace(tfd, "foo", tfd, "bar") >= 0);
+        assert_se(linkat_replace(tfd, "foo", tfd, "bar") >= 0);
+
+        _cleanup_close_ int fd1_check = openat(tfd, "bar", O_RDWR|O_CLOEXEC);
+        assert_se(fd1_check >= 0);
+
+        assert_se(inode_same_at(fd1, NULL, fd1_check, NULL, AT_EMPTY_PATH) > 0);
+
+        _cleanup_close_ int fd2 = openat(tfd, "baz", O_CREAT|O_RDWR|O_CLOEXEC, 0600);
+        assert_se(fd2 >= 0);
+
+        assert_se(inode_same_at(fd1, NULL, fd2, NULL, AT_EMPTY_PATH) == 0);
+
+        assert_se(linkat_replace(tfd, "foo", tfd, "baz") >= 0);
+
+        _cleanup_close_ int fd2_check = openat(tfd, "baz", O_RDWR|O_CLOEXEC);
+
+        assert_se(inode_same_at(fd2, NULL, fd2_check, NULL, AT_EMPTY_PATH) == 0);
+        assert_se(inode_same_at(fd1, NULL, fd2_check, NULL, AT_EMPTY_PATH) > 0);
+}
+
 static int intro(void) {
         arg_test_dir = saved_argv[1];
         return EXIT_SUCCESS;
index fa5923eb2777212aba948e4480312524bd28f4a0..825aac65080db8fe9f0c454474a908360240ba8d 100644 (file)
@@ -34,15 +34,15 @@ TEST(gpt_types_against_architectures) {
                                 printf("%s %s\n", GREEN_CHECK_MARK(), joined);
 
                                 if (streq(prefix, "root-") && streq(suffix, ""))
-                                        assert_se(type.designator == PARTITION_ROOT);
+                                        ASSERT_EQ(type.designator, PARTITION_ROOT);
                                 if (streq(prefix, "root-") && streq(suffix, "-verity"))
-                                        assert_se(type.designator == PARTITION_ROOT_VERITY);
+                                        ASSERT_EQ(type.designator, PARTITION_ROOT_VERITY);
                                 if (streq(prefix, "usr-") && streq(suffix, ""))
-                                        assert_se(type.designator == PARTITION_USR);
+                                        ASSERT_EQ(type.designator, PARTITION_USR);
                                 if (streq(prefix, "usr-") && streq(suffix, "-verity"))
-                                        assert_se(type.designator == PARTITION_USR_VERITY);
+                                        ASSERT_EQ(type.designator, PARTITION_USR_VERITY);
 
-                                assert_se(type.arch == a);
+                                ASSERT_EQ(type.arch, a);
                         }
 }
 
@@ -72,38 +72,38 @@ TEST(type_alias_same) {
                 GptPartitionType x, y;
 
                 x = gpt_partition_type_from_uuid(t->uuid);                   /* search first by uuid */
-                assert_se(gpt_partition_type_from_string(t->name, &y) >= 0); /* search first by name */
+                ASSERT_GE(gpt_partition_type_from_string(t->name, &y), 0); /* search first by name */
 
-                assert_se(t->arch == x.arch);
-                assert_se(t->arch == y.arch);
-                assert_se(t->designator == x.designator);
-                assert_se(t->designator == y.designator);
+                ASSERT_EQ(t->arch, x.arch);
+                ASSERT_EQ(t->arch, y.arch);
+                ASSERT_EQ(t->designator, x.designator);
+                ASSERT_EQ(t->designator, y.designator);
         }
 }
 
 TEST(override_architecture) {
         GptPartitionType x, y;
 
-        assert_se(gpt_partition_type_from_string("root-x86-64", &x) >= 0);
-        assert_se(x.arch == ARCHITECTURE_X86_64);
+        ASSERT_GE(gpt_partition_type_from_string("root-x86-64", &x), 0);
+        ASSERT_EQ(x.arch, ARCHITECTURE_X86_64);
 
-        assert_se(gpt_partition_type_from_string("root-arm64", &y) >= 0);
-        assert(y.arch == ARCHITECTURE_ARM64);
+        ASSERT_GE(gpt_partition_type_from_string("root-arm64", &y), 0);
+        ASSERT_EQ(y.arch, ARCHITECTURE_ARM64);
 
         x = gpt_partition_type_override_architecture(x, ARCHITECTURE_ARM64);
-        assert_se(x.arch == y.arch);
-        assert_se(x.designator == y.designator);
+        ASSERT_EQ(x.arch, y.arch);
+        ASSERT_EQ(x.designator, y.designator);
         assert_se(sd_id128_equal(x.uuid, y.uuid));
         assert_se(streq(x.name, y.name));
 
         /* If the partition type does not have an architecture, nothing should change. */
 
-        assert_se(gpt_partition_type_from_string("esp", &x) >= 0);
+        ASSERT_GE(gpt_partition_type_from_string("esp", &x), 0);
         y = x;
 
         x = gpt_partition_type_override_architecture(x, ARCHITECTURE_ARM64);
-        assert_se(x.arch == y.arch);
-        assert_se(x.designator == y.designator);
+        ASSERT_EQ(x.arch, y.arch);
+        ASSERT_EQ(x.designator, y.designator);
         assert_se(sd_id128_equal(x.uuid, y.uuid));
         assert_se(streq(x.name, y.name));
 }
index 5daa0e64f6542d40a24882a5fadf39601de71402..cf4fca27e3f7aef5b55cf9658004d449eddff689 100644 (file)
@@ -42,7 +42,7 @@ TEST(trivial_compare_func) {
 }
 
 TEST(string_compare_func) {
-        assert_se(string_compare_func("fred", "wilma") != 0);
+        ASSERT_NE(string_compare_func("fred", "wilma"), 0);
         assert_se(string_compare_func("fred", "fred") == 0);
 }
 
index 1b788b191c0b76cf5c6106d095e38e29aa137d00..18c81adbcdbfbdb9df3a792be946561f11c10597 100644 (file)
@@ -19,7 +19,7 @@ TEST(hmac) {
                               "",
                               result);
         hex_result = hexmem(result, sizeof(result));
-        assert_se(streq_ptr(hex_result, "cadd5e42114351181f3abff477641d88efb57d2b5641a1e5c6d623363a6d3bad"));
+        ASSERT_STREQ(hex_result, "cadd5e42114351181f3abff477641d88efb57d2b5641a1e5c6d623363a6d3bad");
         hex_result = mfree(hex_result);
 
         hmac_sha256_by_string("waldo",
index efd75b2a6798b70205d5bea42e697b572ffc2f46..c55445079c6c6fc62f19033c4966074b629d2a40 100644 (file)
@@ -200,7 +200,7 @@ TEST(basic_mask_and_enable) {
 }
 
 TEST(linked_units) {
-        const char *p, *q;
+        const char *p, *q, *s;
         UnitFileState state;
         InstallChange *changes = NULL;
         size_t n_changes = 0, i;
@@ -224,6 +224,7 @@ TEST(linked_units) {
         p = strjoina(root, "/opt/linked.service");
         assert_se(write_string_file(p,
                                     "[Install]\n"
+                                    "Alias=linked-alias.service\n"
                                     "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
 
         p = strjoina(root, "/opt/linked2.service");
@@ -275,31 +276,41 @@ TEST(linked_units) {
 
         /* Now, let's not just link it, but also enable it */
         assert_se(unit_file_enable(RUNTIME_SCOPE_SYSTEM, 0, root, STRV_MAKE("/opt/linked.service"), &changes, &n_changes) >= 0);
-        assert_se(n_changes == 2);
+        assert_se(n_changes == 3);
         p = strjoina(root, SYSTEM_CONFIG_UNIT_DIR"/multi-user.target.wants/linked.service");
         q = strjoina(root, SYSTEM_CONFIG_UNIT_DIR"/linked.service");
+        s = strjoina(root, SYSTEM_CONFIG_UNIT_DIR"/linked-alias.service");
         for (i = 0 ; i < n_changes; i++) {
                 assert_se(changes[i].type == INSTALL_CHANGE_SYMLINK);
-                assert_se(streq(changes[i].source, "/opt/linked.service"));
+
+                if (s && streq(changes[i].path, s))
+                        /* The alias symlink should point within the search path. */
+                        assert_se(streq(changes[i].source, SYSTEM_CONFIG_UNIT_DIR"/linked.service"));
+                else
+                        assert_se(streq(changes[i].source, "/opt/linked.service"));
 
                 if (p && streq(changes[i].path, p))
                         p = NULL;
                 else if (q && streq(changes[i].path, q))
                         q = NULL;
+                else if (s && streq(changes[i].path, s))
+                        s = NULL;
                 else
                         assert_not_reached();
         }
-        assert_se(!p && !q);
+        assert_se(!p && !q && !s);
         install_changes_free(changes, n_changes);
         changes = NULL; n_changes = 0;
 
         assert_se(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+        assert_se(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "linked-alias.service", &state) >= 0 && state == UNIT_FILE_ALIAS);
 
         /* And let's unlink it again */
         assert_se(unit_file_disable(RUNTIME_SCOPE_SYSTEM, 0, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
-        assert_se(n_changes == 2);
+        assert_se(n_changes == 3);
         p = strjoina(root, SYSTEM_CONFIG_UNIT_DIR"/multi-user.target.wants/linked.service");
         q = strjoina(root, SYSTEM_CONFIG_UNIT_DIR"/linked.service");
+        s = strjoina(root, SYSTEM_CONFIG_UNIT_DIR"/linked-alias.service");
         for (i = 0; i < n_changes; i++) {
                 assert_se(changes[i].type == INSTALL_CHANGE_UNLINK);
 
@@ -307,10 +318,12 @@ TEST(linked_units) {
                         p = NULL;
                 else if (q && streq(changes[i].path, q))
                         q = NULL;
+                else if (s && streq(changes[i].path, s))
+                        s = NULL;
                 else
                         assert_not_reached();
         }
-        assert_se(!p && !q);
+        assert_se(!p && !q && !s);
         install_changes_free(changes, n_changes);
         changes = NULL; n_changes = 0;
 
diff --git a/src/test/test-label.c b/src/test/test-label.c
new file mode 100644 (file)
index 0000000..9d7ac18
--- /dev/null
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "errno-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "label.h"
+#include "path-util.h"
+#include "string-util.h"
+#include "tests.h"
+
+static struct stat buf;
+static int check_path(int dir_fd, const char *path) {
+        assert(path);
+        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
+
+        if (isempty(path))
+                return -EINVAL;
+
+        /* assume length of pathname is not greater than 40*/
+        if (strlen(path) > 40)
+                return -ENAMETOOLONG;
+
+        /* assume a case where a specific label isn't allowed */
+        if (path_equal(path, "/restricted_directory"))
+                return -EACCES;
+        return 0;
+}
+
+static int pre_labelling_func(int dir_fd, const char *path, mode_t mode) {
+        int r;
+
+        assert(mode != MODE_INVALID);
+        r = check_path(dir_fd, path);
+        if (r < 0)
+                return log_error_errno(r, "Error in pathname =>: %m");
+
+        return 0;
+}
+
+static int post_labelling_func(int dir_fd, const char *path) {
+       int r;
+
+        /* assume label policies that restrict certain labels */
+        r = check_path(dir_fd, path);
+        if (r < 0)
+                return log_error_errno(r, "Error in pathname =>: %m");
+
+        /* Set file data to buf */
+        r = RET_NERRNO(fstatat(dir_fd, path, &buf, 0));
+        if (r < 0)
+                return log_error_errno(r, "Error in getting file status =>: %m");
+
+        return 0; /* on success */
+}
+
+static int get_dir_fd(const char *dir_path, mode_t mode) {
+        /* create a new directory and return its descriptor*/
+        int dir_fd = -EBADF;
+
+        assert(dir_path);
+        dir_fd = RET_NERRNO(open_mkdir_at(AT_FDCWD, dir_path, O_CLOEXEC, mode));
+        if (dir_fd < 0)
+                return log_error_errno(dir_fd, "Error occurred while opening directory =>: %m");
+
+        return dir_fd;
+}
+
+static int labelling_op(int dir_fd, const char *text, const char *path, mode_t mode) {
+        /* Write some content into the file */
+        ssize_t count;
+        _cleanup_close_ int write_fd = -EBADF;
+        int r;
+
+        assert(text);
+        assert(mode != MODE_INVALID);
+        r = check_path(dir_fd, path);
+        if (r < 0)
+                return log_error_errno(r, "Error in pathname =>: %m");
+
+        /* Open the file within the directory for writing*/
+        write_fd = RET_NERRNO(openat(dir_fd, path, O_CLOEXEC|O_WRONLY|O_TRUNC|O_CREAT, 0644));
+        if (write_fd < 0)
+                return log_error_errno(write_fd, "Error in opening directory for writing =>: %m");
+
+        /* Write data to the file*/
+        count = RET_NERRNO(write(write_fd, text, strlen(text)));
+        if (count < 0)
+                return log_error_errno(count, "Error occurred while opening file for writing =>: %m");
+        return 0;
+}
+
+TEST(label_ops_set) {
+        static const LabelOps test_label_ops = {
+                .pre = NULL,
+                .post = NULL,
+        };
+
+        label_ops_reset();
+        assert_se(label_ops_set(&test_label_ops) == 0);
+        /* attempt to reset label_ops when already set */
+        assert_se(label_ops_set(&test_label_ops) == -EBUSY);
+}
+
+TEST(label_ops_pre) {
+        _cleanup_close_ int fd;
+        static const LabelOps test_label_ops = {
+                .pre = pre_labelling_func,
+                .post = NULL,
+        };
+
+        label_ops_reset();
+        label_ops_set(&test_label_ops);
+        fd = get_dir_fd("file1.txt", 0755);
+        assert_se(label_ops_pre(fd, "file1.txt", 0644) == 0);
+        assert_se(label_ops_pre(fd, "/restricted_directory", 0644) == -EACCES);
+        assert_se(label_ops_pre(fd, "", 0700) == -EINVAL);
+        assert_se(label_ops_pre(fd, "/tmp", 0700) == 0);
+        assert_se(label_ops_pre(fd, "wekrgoierhgoierhqgherhgwklegnlweehgorwfkryrit", 0644) == -ENAMETOOLONG);
+}
+
+TEST(label_ops_post) {
+        _cleanup_close_ int fd = -EBADF;
+        const char *text1, *text2;
+        static const LabelOps test_label_ops = {
+                .pre = NULL,
+                .post = post_labelling_func,
+        };
+
+        label_ops_reset();
+        label_ops_set(&test_label_ops);
+
+        /* Open directory */
+        fd = RET_NERRNO(get_dir_fd("label_test_dir", 0755));
+        text1 = "Add initial texts to file for testing label operations to file1\n";
+
+        assert(labelling_op(fd, text1, "file1.txt", 0644) == 0);
+        assert_se(label_ops_post(fd, "file1.txt") == 0);
+        assert_se(strlen(text1) == (size_t)buf.st_size);
+        text2 = "Add text2 data to file2\n";
+
+        assert(labelling_op(fd, text2, "file2.txt", 0644) == 0);
+        assert_se(label_ops_post(fd, "file2.txt") == 0);
+        assert_se(strlen(text2) == (size_t)buf.st_size);
+        assert_se(label_ops_post(fd, "file3.txt") == -ENOENT);
+        assert_se(label_ops_post(fd, "/abcd") == -ENOENT);
+        assert_se(label_ops_post(fd, "/restricted_directory") == -EACCES);
+        assert_se(label_ops_post(fd, "") == -EINVAL);
+}
+
+DEFINE_TEST_MAIN(LOG_INFO)
index 6d784a9ae83cc422d810a28ca5017e1376853346..affcaccc007fa8f961cb76f5808eb47565b792dd 100644 (file)
@@ -152,7 +152,7 @@ TEST(path_is_mount_point) {
          */
 
         /* file mountpoints */
-        assert_se(mkdtemp(tmp_dir) != NULL);
+        ASSERT_NOT_NULL(mkdtemp(tmp_dir));
         file1 = path_join(tmp_dir, "file1");
         assert_se(file1);
         file2 = path_join(tmp_dir, "file2");
index 84e55e175445bfc63cbb5b5354d7ef5f4484f0b5..e51ab9d29086bb28f7543e3f88e1bd683962cbeb 100644 (file)
 #include "tmpfile-util.h"
 
 TEST(path_is_os_tree) {
-        assert_se(path_is_os_tree("/") > 0);
-        assert_se(path_is_os_tree("/etc") == 0);
+        ASSERT_GT(path_is_os_tree("/"), 0);
+        ASSERT_EQ(path_is_os_tree("/etc"), 0);
         assert_se(path_is_os_tree("/idontexist") == -ENOENT);
 }
 
 TEST(parse_os_release) {
         /* Let's assume that we're running in a valid system, so os-release is available */
         _cleanup_free_ char *id = NULL, *id2 = NULL, *name = NULL, *foobar = NULL;
-        assert_se(parse_os_release(NULL, "ID", &id) == 0);
+        ASSERT_EQ(parse_os_release(NULL, "ID", &id), 0);
         log_info("ID: %s", id);
 
-        assert_se(setenv("SYSTEMD_OS_RELEASE", "/dev/null", 1) == 0);
-        assert_se(parse_os_release(NULL, "ID", &id2) == 0);
+        ASSERT_EQ(setenv("SYSTEMD_OS_RELEASE", "/dev/null", 1), 0);
+        ASSERT_EQ(parse_os_release(NULL, "ID", &id2), 0);
         log_info("ID: %s", strnull(id2));
 
         _cleanup_(unlink_tempfilep) char tmpfile[] = "/tmp/test-os-util.XXXXXX";
-        assert_se(write_tmpfile(tmpfile,
+        ASSERT_EQ(write_tmpfile(tmpfile,
                                 "ID=the-id  \n"
-                                "NAME=the-name") == 0);
+                                "NAME=the-name"), 0);
 
-        assert_se(setenv("SYSTEMD_OS_RELEASE", tmpfile, 1) == 0);
-        assert_se(parse_os_release(NULL, "ID", &id, "NAME", &name) == 0);
+        ASSERT_EQ(setenv("SYSTEMD_OS_RELEASE", tmpfile, 1), 0);
+        ASSERT_EQ(parse_os_release(NULL, "ID", &id, "NAME", &name), 0);
         log_info("ID: %s NAME: %s", id, name);
         assert_se(streq(id, "the-id"));
         assert_se(streq(name, "the-name"));
 
         _cleanup_(unlink_tempfilep) char tmpfile2[] = "/tmp/test-os-util.XXXXXX";
-        assert_se(write_tmpfile(tmpfile2,
+        ASSERT_EQ(write_tmpfile(tmpfile2,
                                 "ID=\"ignored\"  \n"
                                 "ID=\"the-id\"  \n"
-                                "NAME='the-name'") == 0);
+                                "NAME='the-name'"), 0);
 
-        assert_se(setenv("SYSTEMD_OS_RELEASE", tmpfile2, 1) == 0);
-        assert_se(parse_os_release(NULL, "ID", &id, "NAME", &name) == 0);
+        ASSERT_EQ(setenv("SYSTEMD_OS_RELEASE", tmpfile2, 1), 0);
+        ASSERT_EQ(parse_os_release(NULL, "ID", &id, "NAME", &name), 0);
         log_info("ID: %s NAME: %s", id, name);
         assert_se(streq(id, "the-id"));
         assert_se(streq(name, "the-name"));
 
-        assert_se(parse_os_release(NULL, "FOOBAR", &foobar) == 0);
+        ASSERT_EQ(parse_os_release(NULL, "FOOBAR", &foobar), 0);
         log_info("FOOBAR: %s", strnull(foobar));
-        assert_se(foobar == NULL);
+        ASSERT_NULL(foobar);
 
         assert_se(unsetenv("SYSTEMD_OS_RELEASE") == 0);
 }
@@ -70,6 +70,7 @@ TEST(parse_extension_release) {
 
         assert_se(a = path_join(tempdir, "/usr/lib/extension-release.d/extension-release.test"));
         assert_se(mkdir_parents(a, 0777) >= 0);
+        ASSERT_GE(mkdir_parents(a, 0777), 0);
 
         r = write_string_file(a, "ID=the-id  \n VERSION_ID=the-version-id", WRITE_STRING_FILE_CREATE);
         if (r < 0)
@@ -87,42 +88,42 @@ TEST(parse_extension_release) {
         if (r < 0)
                 log_error_errno(r, "Failed to write file: %m");
 
-        assert_se(parse_extension_release(tempdir, IMAGE_CONFEXT, "tester", false, "ID", &id, "VERSION_ID", &version_id) == 0);
+        ASSERT_EQ(parse_extension_release(tempdir, IMAGE_CONFEXT, "tester", false, "ID", &id, "VERSION_ID", &version_id), 0);
         log_info("ID: %s VERSION_ID: %s", id, version_id);
         assert_se(streq(id, "the-id"));
         assert_se(streq(version_id, "the-version-id"));
 
         assert_se(parse_extension_release(tempdir, IMAGE_CONFEXT, "tester", false, "FOOBAR", &foobar) == 0);
         log_info("FOOBAR: %s", strnull(foobar));
-        assert_se(foobar == NULL);
+        ASSERT_NULL(foobar);
 
         assert_se(parse_extension_release(tempdir, IMAGE_SYSEXT, "test", false, "FOOBAR", &foobar) == 0);
         log_info("FOOBAR: %s", strnull(foobar));
-        assert_se(foobar == NULL);
+        ASSERT_NULL(foobar);
 }
 
 TEST(load_os_release_pairs) {
         _cleanup_(unlink_tempfilep) char tmpfile[] = "/tmp/test-os-util.XXXXXX";
-        assert_se(write_tmpfile(tmpfile,
+        ASSERT_EQ(write_tmpfile(tmpfile,
                                 "ID=\"ignored\"  \n"
                                 "ID=\"the-id\"  \n"
-                                "NAME='the-name'") == 0);
+                                "NAME='the-name'"), 0);
 
-        assert_se(setenv("SYSTEMD_OS_RELEASE", tmpfile, 1) == 0);
+        ASSERT_EQ(setenv("SYSTEMD_OS_RELEASE", tmpfile, 1), 0);
 
         _cleanup_strv_free_ char **pairs = NULL;
-        assert_se(load_os_release_pairs(NULL, &pairs) == 0);
+        ASSERT_EQ(load_os_release_pairs(NULL, &pairs), 0);
         assert_se(strv_equal(pairs, STRV_MAKE("ID", "the-id",
                                               "NAME", "the-name")));
 
-        assert_se(unsetenv("SYSTEMD_OS_RELEASE") == 0);
+        ASSERT_EQ(unsetenv("SYSTEMD_OS_RELEASE"), 0);
 }
 
 TEST(os_release_support_ended) {
         int r;
 
-        assert_se(os_release_support_ended("1999-01-01", false, NULL) == true);
-        assert_se(os_release_support_ended("2037-12-31", false, NULL) == false);
+        ASSERT_TRUE(os_release_support_ended("1999-01-01", false, NULL));
+        ASSERT_FALSE(os_release_support_ended("2037-12-31", false, NULL));
         assert_se(os_release_support_ended("-1-1-1", true, NULL) == -EINVAL);
 
         r = os_release_support_ended(NULL, false, NULL);
index f5a425689a3f0a9481484e6916e481d0ea47a717..ceff01967aa0a408d44e682fc02f62b0dac4e2bc 100644 (file)
@@ -506,24 +506,24 @@ TEST(prefixes) {
                 log_error("---%s---", s);
                 assert_se(streq(s, values[i++]));
         }
-        assert_se(values[i] == NULL);
+        ASSERT_NULL(values[i]);
 
         i = 1;
         PATH_FOREACH_PREFIX(s, "/a/b/c/d") {
                 log_error("---%s---", s);
                 assert_se(streq(s, values[i++]));
         }
-        assert_se(values[i] == NULL);
+        ASSERT_NULL(values[i]);
 
         i = 0;
         PATH_FOREACH_PREFIX_MORE(s, "////a////b////c///d///////")
                 assert_se(streq(s, values[i++]));
-        assert_se(values[i] == NULL);
+        ASSERT_NULL(values[i]);
 
         i = 1;
         PATH_FOREACH_PREFIX(s, "////a////b////c///d///////")
                 assert_se(streq(s, values[i++]));
-        assert_se(values[i] == NULL);
+        ASSERT_NULL(values[i]);
 
         PATH_FOREACH_PREFIX(s, "////")
                 assert_not_reached();
@@ -1305,4 +1305,28 @@ TEST(print_MAX) {
         assert_cc(FILENAME_MAX == PATH_MAX);
 }
 
+TEST(path_implies_directory) {
+        assert_se(!path_implies_directory(NULL));
+        assert_se(!path_implies_directory(""));
+        assert_se(path_implies_directory("/"));
+        assert_se(path_implies_directory("////"));
+        assert_se(path_implies_directory("////.///"));
+        assert_se(path_implies_directory("////./"));
+        assert_se(path_implies_directory("////."));
+        assert_se(path_implies_directory("."));
+        assert_se(path_implies_directory("./"));
+        assert_se(path_implies_directory("/."));
+        assert_se(path_implies_directory(".."));
+        assert_se(path_implies_directory("../"));
+        assert_se(path_implies_directory("/.."));
+        assert_se(!path_implies_directory("a"));
+        assert_se(!path_implies_directory("ab"));
+        assert_se(path_implies_directory("ab/"));
+        assert_se(!path_implies_directory("ab/a"));
+        assert_se(path_implies_directory("ab/a/"));
+        assert_se(path_implies_directory("ab/a/.."));
+        assert_se(path_implies_directory("ab/a/."));
+        assert_se(path_implies_directory("ab/a//"));
+}
+
 DEFINE_TEST_MAIN(LOG_DEBUG);
index 52b2bc861e8a8e8b6bf4a89e23acdf0709295621..9ab52c60129f168f9a4f6e5bdcee7dbf05fb63ef 100644 (file)
@@ -22,7 +22,7 @@ static void test_draw_cylon_one(unsigned pos) {
 
         memset(buf, 0xff, sizeof(buf));
         draw_cylon(buf, sizeof(buf), CYLON_WIDTH, pos);
-        assert_se(strlen(buf) < sizeof(buf));
+        ASSERT_LE(strlen(buf), sizeof(buf));
 }
 
 TEST(draw_cylon) {
diff --git a/src/test/test-recovery-key.c b/src/test/test-recovery-key.c
new file mode 100644 (file)
index 0000000..2e901dc
--- /dev/null
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <string.h>
+
+#include "memory-util.h"
+#include "random-util.h"
+#include "recovery-key.h"
+#include "tests.h"
+
+TEST(make_recovery_key) {
+        _cleanup_(erase_and_freep) char *recovery_key = NULL;
+        size_t length;
+        const size_t num_test = 10;
+        char *generated_keys[num_test];
+        int r;
+
+        /* Check for successful recovery-key creation */
+        r = make_recovery_key(&recovery_key);
+        assert_se(r == 0);
+        ASSERT_NOT_NULL(recovery_key);
+
+        /* Check that length of formatted key is 72 with 64 modhex characters */
+        length = strlen(recovery_key);
+        assert_se(length == RECOVERY_KEY_MODHEX_FORMATTED_LENGTH - 1);
+        /* Check modhex characters in formatted key with dashes */
+        for (size_t i = 0; i < length; i++) {
+                assert_se((recovery_key[i] >= 'a' && recovery_key[i] <= 'v') || recovery_key[i] == '-');
+                if (i % 9 == 8)
+                        /* confirm '-' is after every 8 characters */
+                        assert_se(recovery_key[i] == '-');
+        }
+        /* Repeat tests to determine randomness of generated keys */
+        for (size_t test = 0; test < num_test; ++test) {
+                r = make_recovery_key(&generated_keys[test]);
+                assert_se(r == 0);
+                length = strlen(generated_keys[test]);
+                assert_se(length == RECOVERY_KEY_MODHEX_FORMATTED_LENGTH - 1);
+                for (size_t i = 0; i < length; i++) {
+                        assert_se((generated_keys[test][i] >= 'a' && generated_keys[test][i] <= 'v')
+                                || generated_keys[test][i] == '-');
+                        if (i % 9 == 8)
+                                assert_se(generated_keys[test][i] == '-');
+                }
+                /* Check for uniqueness of each generated recovery key */
+                for (size_t prev = 0; prev < test; ++prev)
+                        assert_se(!streq(generated_keys[test], generated_keys[prev]));
+        }
+        for (size_t i = 0; i < num_test; i++)
+                free(generated_keys[i]);
+}
+
+TEST(decode_modhex_char) {
+
+        assert_se(decode_modhex_char('c') == 0);
+        assert_se(decode_modhex_char('C') == 0);
+        assert_se(decode_modhex_char('b') == 1);
+        assert_se(decode_modhex_char('B') == 1);
+        assert_se(decode_modhex_char('d') == 2);
+        assert_se(decode_modhex_char('D') == 2);
+        assert_se(decode_modhex_char('e') == 3);
+        assert_se(decode_modhex_char('E') == 3);
+        assert_se(decode_modhex_char('f') == 4);
+        assert_se(decode_modhex_char('F') == 4);
+        assert_se(decode_modhex_char('g') == 5);
+        assert_se(decode_modhex_char('G') == 5);
+        assert_se(decode_modhex_char('h') == 6);
+        assert_se(decode_modhex_char('H') == 6);
+        assert_se(decode_modhex_char('i') == 7);
+        assert_se(decode_modhex_char('I') == 7);
+        assert_se(decode_modhex_char('j') == 8);
+        assert_se(decode_modhex_char('J') == 8);
+        assert_se(decode_modhex_char('k') == 9);
+        assert_se(decode_modhex_char('K') == 9);
+        assert_se(decode_modhex_char('l') == 10);
+        assert_se(decode_modhex_char('L') == 10);
+        assert_se(decode_modhex_char('n') == 11);
+        assert_se(decode_modhex_char('N') == 11);
+        assert_se(decode_modhex_char('r') == 12);
+        assert_se(decode_modhex_char('R') == 12);
+        assert_se(decode_modhex_char('t') == 13);
+        assert_se(decode_modhex_char('T') == 13);
+        assert_se(decode_modhex_char('u') == 14);
+        assert_se(decode_modhex_char('U') == 14);
+        assert_se(decode_modhex_char('v') == 15);
+        assert_se(decode_modhex_char('V') == 15);
+        assert_se(decode_modhex_char('a') == -EINVAL);
+        assert_se(decode_modhex_char('A') == -EINVAL);
+        assert_se(decode_modhex_char('x') == -EINVAL);
+        assert_se(decode_modhex_char('.') == -EINVAL);
+        assert_se(decode_modhex_char('/') == -EINVAL);
+        assert_se(decode_modhex_char('\0') == -EINVAL);
+}
+
+TEST(normalize_recovery_key) {
+        _cleanup_(erase_and_freep) char *normalized_key1 = NULL;
+        _cleanup_(erase_and_freep) char *normalized_key2 = NULL;
+        _cleanup_(erase_and_freep) char *normalized_key3 = NULL;
+        int r;
+
+        /* Case 1: Normalization without dashes */
+        r = normalize_recovery_key("cdefghijcdefghijcdefghijcdefghijcdefghijcdefghijcdefghijcdefghij",
+                        &normalized_key1);
+        assert(r == 0);
+        assert(streq(normalized_key1, "cdefghij-cdefghij-cdefghij-cdefghij-cdefghij-cdefghij-cdefghij-cdefghij"));
+
+        /* Case 2: Normalization with dashes */
+        r = normalize_recovery_key("cdefVhij-cDefghij-cdefkhij-cdufghij-cdefgdij-cidefIhj-cdefNijR-cdVfguij",
+                        &normalized_key2);
+        assert_se(r == 0);
+        assert_se(streq(normalized_key2, "cdefvhij-cdefghij-cdefkhij-cdufghij-cdefgdij-cidefihj-cdefnijr-cdvfguij"));
+
+        /* Case 3: Invalid password length */
+        r = normalize_recovery_key("1234-5678-90AB-CDEF-1234-5678-90AB-CDEF", &normalized_key1);
+        assert(r == -EINVAL);
+
+        /* Case 4: Invalid password format(missing dash) */
+        r = normalize_recovery_key("cdefghij-cdefghij-cdefghij-cdefghij-cdefghij-cdefghij-cdefghijcdefghij",
+                        &normalized_key1);
+        assert_se(r == -EINVAL);
+
+        /* Case 5: Normalization of Upper cases password without dashes */
+        r = normalize_recovery_key("BFGHICEHHIUVLKJIHFHEDlntruvcdefjiTUVKLNIJVTUTKJIHDFBCBGHIJHHFDBC",
+                        &normalized_key3);
+        assert(r == 0);
+        assert_se(streq(normalized_key3, "bfghiceh-hiuvlkji-hfhedlnt-ruvcdefj-ituvklni-jvtutkji-hdfbcbgh-ijhhfdbc"));
+
+        /* Case 6: Minimum password length */
+        r = normalize_recovery_key("", &normalized_key1);
+        assert_se(r == -EINVAL);
+
+        /* Case 7: Invalid characters and numbers in password */
+        r = normalize_recovery_key("cde123hi-cdefgzij-cdefghij-cdefghij-cdefghij-cdefghij-cdefghijcdefghij",
+                        &normalized_key1);
+        assert_se(r == -EINVAL);
+}
+
+DEFINE_TEST_MAIN(LOG_INFO);
index 92f1083a4c5047b2958fea1f17dfcef216ae91fc..3b003e885f0d3af249d40b0014c3a1674f068cc4 100644 (file)
@@ -88,6 +88,35 @@ TEST(free_and_strndup) {
         }
 }
 
+TEST(strdup_to_full) {
+        _cleanup_free_ char *dst;
+
+        assert_se(strdup_to_full(NULL, NULL) == 0);
+        assert_se(strdup_to_full(&dst, NULL) == 0);
+
+        assert_se(strdup_to_full(NULL, "") == 1);
+        assert_se(strdup_to_full(&dst, "") == 1);
+        assert_se(streq_ptr(dst, ""));
+        dst = mfree(dst);
+
+        assert_se(strdup_to_full(NULL, "x") == 1);
+        assert_se(strdup_to_full(&dst, "x") == 1);
+        assert_se(streq_ptr(dst, "x"));
+}
+
+TEST(strdup_to) {
+        _cleanup_free_ char *dst;
+
+        assert_se(strdup_to(&dst, NULL) == 0);
+
+        assert_se(strdup_to(&dst, "") == 0);
+        assert_se(streq_ptr(dst, ""));
+        dst = mfree(dst);
+
+        assert_se(strdup_to(&dst, "x") == 0);
+        assert_se(streq_ptr(dst, "x"));
+}
+
 TEST(ascii_strcasecmp_n) {
         assert_se(ascii_strcasecmp_n("", "", 0) == 0);
         assert_se(ascii_strcasecmp_n("", "", 1) == 0);
index db76cde0a263c4b301b6cff11d64f35d595b8b52..f115a477738e67f5b7712cb640be6e272a8b26c0 100644 (file)
@@ -137,8 +137,8 @@ TEST(parse_uid) {
 }
 
 TEST(uid_ptr) {
-        assert_se(UID_TO_PTR(0) != NULL);
-        assert_se(UID_TO_PTR(1000) != NULL);
+        ASSERT_NOT_NULL(UID_TO_PTR(0));
+        ASSERT_NOT_NULL(UID_TO_PTR(1000));
 
         assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
         assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
index 0be7ffc6a5fff66f202b6be0a41b2463577ed7d8..846d5b8ac8389005e5a62967983327712f604304 100644 (file)
@@ -18,6 +18,7 @@
 
 static char *arg_tpm2_device = NULL;
 static bool arg_early = false;
+static bool arg_graceful = false;
 
 STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
 
@@ -43,6 +44,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --tpm2-device=PATH\n"
                "                          Pick TPM2 device\n"
                "     --early=BOOL         Store SRK public key in /run/ rather than /var/lib/\n"
+               "     --graceful           Exit gracefully if no TPM2 device is found\n"
                "\nSee the %2$s for details.\n",
                program_invocation_short_name,
                link,
@@ -59,6 +61,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_VERSION = 0x100,
                 ARG_TPM2_DEVICE,
                 ARG_EARLY,
+                ARG_GRACEFUL,
         };
 
         static const struct option options[] = {
@@ -66,6 +69,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "version",     no_argument,       NULL, ARG_VERSION     },
                 { "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
                 { "early",       required_argument, NULL, ARG_EARLY       },
+                { "graceful",    no_argument,       NULL, ARG_GRACEFUL    },
                 {}
         };
 
@@ -100,6 +104,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_early = r;
                         break;
 
+                case ARG_GRACEFUL:
+                        arg_graceful = true;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -247,6 +255,11 @@ static int run(int argc, char *argv[]) {
         if (r <= 0)
                 return r;
 
+        if (arg_graceful && tpm2_support() != TPM2_SUPPORT_FULL) {
+                log_notice("No complete TPM2 support detected, exiting gracefully.");
+                return EXIT_SUCCESS;
+        }
+
         umask(0022);
 
         _cleanup_(public_key_data_done) struct public_key_data runtime_key = {}, persistent_key = {}, tpm2_key = {};
index 5ab0053be9142e27a48e2ce431d72875286a9048..8d2348d74872846d863cd5ba6a98b601785b80d2 100644 (file)
@@ -13,6 +13,7 @@
 #include "dirent-util.h"
 #include "fd-util.h"
 #include "discover-image.h"
+#include "pidref.h"
 #include "sd-daemon.h"
 #include "sd-event.h"
 #include "sd-id128.h"
@@ -33,6 +34,7 @@
 #include "gpt.h"
 #include "hexdecoct.h"
 #include "hostname-util.h"
+#include "io-util.h"
 #include "kernel-image.h"
 #include "log.h"
 #include "machine-credential.h"
@@ -54,6 +56,7 @@
 #include "stat-util.h"
 #include "string-util.h"
 #include "strv.h"
+#include "time-util.h"
 #include "tmpfile-util.h"
 #include "unit-name.h"
 #include "vmspawn-mount.h"
@@ -92,6 +95,8 @@ static sd_id128_t arg_uuid = {};
 static char **arg_kernel_cmdline_extra = NULL;
 static char **arg_extra_drives = NULL;
 static char *arg_background = NULL;
+static bool arg_pass_ssh_key = true;
+static char *arg_ssh_key_type = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_directory, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
@@ -107,6 +112,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_forward_journal, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_kernel_cmdline_extra, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_extra_drives, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_background, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_ssh_key_type, freep);
 
 static int help(void) {
         _cleanup_free_ char *link = NULL;
@@ -158,6 +164,8 @@ static int help(void) {
                "\n%3$sIntegration:%4$s\n"
                "     --forward-journal=FILE|DIR\n"
                "                           Forward the VM's journal to the host\n"
+               "     --pass-ssh-key=BOOL   Create an SSH key to access the VM\n"
+               "     --ssh-key-type=TYPE   Choose what type of SSH key to pass\n"
                "\n%3$sInput/Output:%4$s\n"
                "     --console=MODE        Console mode (interactive, native, gui)\n"
                "     --background=COLOR    Set ANSI color for background\n"
@@ -200,6 +208,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_SECURE_BOOT,
                 ARG_PRIVATE_USERS,
                 ARG_FORWARD_JOURNAL,
+                ARG_PASS_SSH_KEY,
+                ARG_SSH_KEY_TYPE,
                 ARG_SET_CREDENTIAL,
                 ARG_LOAD_CREDENTIAL,
                 ARG_FIRMWARE,
@@ -239,6 +249,8 @@ static int parse_argv(int argc, char *argv[]) {
                 { "secure-boot",       required_argument, NULL, ARG_SECURE_BOOT       },
                 { "private-users",     required_argument, NULL, ARG_PRIVATE_USERS     },
                 { "forward-journal",   required_argument, NULL, ARG_FORWARD_JOURNAL   },
+                { "pass-ssh-key",      required_argument, NULL, ARG_PASS_SSH_KEY      },
+                { "ssh-key-type",      required_argument, NULL, ARG_SSH_KEY_TYPE      },
                 { "set-credential",    required_argument, NULL, ARG_SET_CREDENTIAL    },
                 { "load-credential",   required_argument, NULL, ARG_LOAD_CREDENTIAL   },
                 { "firmware",          required_argument, NULL, ARG_FIRMWARE          },
@@ -442,6 +454,23 @@ static int parse_argv(int argc, char *argv[]) {
                                 return r;
                         break;
 
+                case ARG_PASS_SSH_KEY:
+                        r = parse_boolean(optarg);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse --pass-ssh-key= argument: %s", optarg);
+
+                        arg_pass_ssh_key = r;
+                        break;
+
+                case ARG_SSH_KEY_TYPE:
+                        if (!string_is_safe(optarg))
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid value for --arg-ssh-key-type=: %s", optarg);
+
+                        r = free_and_strdup_warn(&arg_ssh_key_type, optarg);
+                        if (r < 0)
+                                return r;
+                        break;
+
                 case ARG_SET_CREDENTIAL: {
                         r = machine_credential_set(&arg_credentials, optarg);
                         if (r < 0)
@@ -1100,11 +1129,55 @@ static void set_window_title(PTYForward *f) {
         if (dot)
                 (void) pty_forward_set_title_prefix(f, dot);
 }
+static int generate_ssh_keypair(const char *key_path, const char *key_type) {
+        _cleanup_free_ char *ssh_keygen = NULL;
+        _cleanup_strv_free_ char **cmdline = NULL;
+        int r;
+
+        assert(key_path);
+
+        r = find_executable("ssh-keygen", &ssh_keygen);
+        if (r < 0)
+                return log_error_errno(r, "Failed to find ssh-keygen: %m");
+
+        cmdline = strv_new(ssh_keygen, "-f", key_path, /* don't encrypt the key */ "-N", "");
+        if (!cmdline)
+                return log_oom();
+
+        if (key_type) {
+                r = strv_extend_many(&cmdline, "-t", key_type);
+                if (r < 0)
+                        return log_oom();
+        }
+
+        if (DEBUG_LOGGING) {
+                _cleanup_free_ char *joined = quote_command_line(cmdline, SHELL_ESCAPE_EMPTY);
+                if (!joined)
+                        return log_oom();
+
+                log_debug("Executing: %s", joined);
+        }
+
+        r = safe_fork(
+                        ssh_keygen,
+                        FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO,
+                        NULL);
+        if (r < 0)
+                return r;
+        if (r == 0) {
+                execv(ssh_keygen, cmdline);
+                log_error_errno(errno, "Failed to execve %s: %m", ssh_keygen);
+                _exit(EXIT_FAILURE);
+        }
+
+        return 0;
+}
 
 static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
         _cleanup_(ovmf_config_freep) OvmfConfig *ovmf_config = NULL;
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         _cleanup_free_ char *machine = NULL, *qemu_binary = NULL, *mem = NULL, *trans_scope = NULL, *kernel = NULL;
+        _cleanup_(rm_rf_physical_and_freep) char *ssh_private_key_path = NULL, *ssh_public_key_path = NULL;
         _cleanup_close_ int notify_sock_fd = -EBADF;
         _cleanup_strv_free_ char **cmdline = NULL;
         _cleanup_free_ int *pass_fds = NULL;
@@ -1683,6 +1756,46 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
                         return r;
         }
 
+        if (arg_pass_ssh_key) {
+                _cleanup_free_ char *scope_prefix = NULL, *privkey_path = NULL, *pubkey_path = NULL;
+                const char *key_type = arg_ssh_key_type ?: "ed25519";
+
+                r = unit_name_to_prefix(trans_scope, &scope_prefix);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to strip .scope suffix from scope: %m");
+
+                privkey_path = strjoin(arg_runtime_directory, "/", scope_prefix, "-", key_type);
+                if (!privkey_path)
+                        return log_oom();
+
+                pubkey_path = strjoin(privkey_path, ".pub");
+                if (!pubkey_path)
+                        return log_oom();
+
+                r = generate_ssh_keypair(privkey_path, key_type);
+                if (r < 0)
+                        return r;
+
+                ssh_private_key_path = TAKE_PTR(privkey_path);
+                ssh_public_key_path = TAKE_PTR(pubkey_path);
+        }
+
+        if (ssh_public_key_path && ssh_private_key_path) {
+                _cleanup_free_ char *scope_prefix = NULL, *cred_path = NULL;
+
+                cred_path = strjoin("ssh.ephemeral-authorized_keys-all:", ssh_public_key_path);
+                if (!cred_path)
+                        return log_oom();
+
+                r = machine_credential_load(&arg_credentials, cred_path);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to load credential %s: %m", cred_path);
+
+                r = unit_name_to_prefix(trans_scope, &scope_prefix);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to strip .scope suffix from scope: %m");
+        }
+
         if (ARCHITECTURE_SUPPORTS_SMBIOS)
                 FOREACH_ARRAY(cred, arg_credentials.credentials, arg_credentials.n_credentials) {
                         _cleanup_free_ char *cred_data_b64 = NULL;
index 42574ce8ea7cfecf782f179132f0359efa1c95df..f8f3a4b3e32cf3f521b3e44ece906004497dbe57 100755 (executable)
@@ -11,9 +11,6 @@ test_append_files() {
     local workspace="${1:?}"
     local dropin_dir
 
-    mkdir -p "$workspace/test-journals/"
-    cp -av "${TEST_BASE_DIR:?}/test-journals/"* "$workspace/test-journals/"
-
     image_install curl setterm unzstd
     image_install -o openssl
     # Necessary for RH-based systems, otherwise MHD fails with:
index d870d57dccf104f123db7f92302fa75c6b624f7a..2ee4a7533abff7a512fcec4845619f54f397f28f 100755 (executable)
@@ -8,9 +8,6 @@ NSPAWN_ARGUMENTS="--private-network"
 # shellcheck source=test/test-functions
 . "${TEST_BASE_DIR:?}/test-functions"
 
-# (Hopefully) a temporary workaround for https://github.com/systemd/systemd/issues/30573
-KERNEL_APPEND="${KERNEL_APPEND:-} SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST=100"
-
 # Make sure vsock is available in the VM
 CID=$((RANDOM + 3))
 QEMU_OPTIONS+=" -device vhost-vsock-pci,guest-cid=$CID"
index b47fa612b15d13d5d54fcccd49ae4b06ee903da4..aadf37a139ea610050bdb9dc1b437782d5c513cf 100644 (file)
@@ -4,6 +4,7 @@ if install_tests
         foreach subdir : [
                 'auxv',
                 'journal-data',
+                'test-journals',
                 'units',
                 'test-execute',
                 'test-fstab-generator',
index ab30928c27185893b9470b4a9616b36bf1fe879f..4ea76e1a94fb45964e64e07fb382087512efc8ba 100755 (executable)
@@ -921,7 +921,7 @@ EOF
 
 # For the networkd instance invoked below cannot support varlink connection.
 # Hence, 'networkctl persistent-storage yes' cannot be used.
-touch /run/systemd/netif/persistent-storage-ready
+export SYSTEMD_NETWORK_PERSISTENT_STORAGE_READY=1
 
 # run networkd as in systemd-networkd.service
 exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ {{ s/^.*=//; s/^[@+-]//; s/^!*//; p}}')
index 833f6093aae832090e1406352ac877718286037e..e1c0c0ae9c00554f8f9b9aa9e0892114abb29768 100755 (executable)
@@ -118,14 +118,12 @@ if [[ ${#ARGS[@]} -ne 0 ]]; then
         RESULTS["$test"]="$result"
         TIMES["$test"]="$SECONDS"
 
-        [[ "$result" -ne 0 ]] && FAILURES=$((FAILURES + 1))
-    done
-fi
-
-# Run clean-again, if requested, and if no tests failed
-if [[ $FAILURES -eq 0 && $CLEAN_AGAIN -eq 1 ]]; then
-    for test in "${!RESULTS[@]}"; do
-        test_run "$test" make -C "$test" clean-again
+        # Run clean-again here to free up space, if requested, and if the test succeeded
+        if [[ "$result" -ne 0 ]]; then
+            FAILURES=$((FAILURES + 1))
+        elif [[ $CLEAN_AGAIN -eq 1 ]]; then
+            test_run "$test" make -C "$test" clean-again
+        fi
     done
 fi
 
index b99580bfd84a8e6f69efee274220bcd81d9f133a..0c0ffa1545edcceea60ee99a2d4dfc65286fcceb 100644 (file)
@@ -3338,6 +3338,13 @@ test_cleanup_again() {
     [ -n "$TESTDIR" ] || return
     rm -rf "$TESTDIR/unprivileged-nspawn-root"
     [[ -n "$initdir" ]] && _umount_dir "$initdir"
+    # Test specific images are not reused, so delete them or we run out of disk space
+    if [[ -n "$IMAGE_PUBLIC" ]] && [ "$(basename "$IMAGE_PUBLIC")" != "default.img" ]; then
+        rm -vf "$IMAGE_PUBLIC"
+    fi
+    if [[ -n "$IMAGE_PRIVATE" ]] && [ "$(basename "$IMAGE_PRIVATE")" != "default.img" ]; then
+        rm -vf "$IMAGE_PRIVATE"
+    fi
 }
 
 test_create_image() {
index 8427f6849bfd9e7921bf9a9a2af40678c9ab1415..5615c900f4861ffa2fe410407a64a2f85573578f 100644 (file)
@@ -534,8 +534,8 @@ test ! -h "$root/etc/systemd/system/link5alias2.service"
 
 "$systemctl" --root="$root" enable '/link5copy.service'
 islink "$root/etc/systemd/system/link5copy.service" '/link5copy.service'
-islink "$root/etc/systemd/system/link5alias.service" '/link5copy.service'
-islink "$root/etc/systemd/system/link5alias2.service" '/link5copy.service'
+islink "$root/etc/systemd/system/link5alias.service" '/etc/systemd/system/link5copy.service'
+islink "$root/etc/systemd/system/link5alias2.service" '/etc/systemd/system/link5copy.service'
 
 "$systemctl" --root="$root" disable 'link5copy.service'
 test ! -h "$root/etc/systemd/system/link5copy.service"
diff --git a/test/units/testsuite-04.cat.sh b/test/units/testsuite-04.cat.sh
new file mode 100755 (executable)
index 0000000..bef3e18
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+systemctl enable --now systemd-journald@cat-test.socket
+
+systemd-cat --namespace cat-test env CAT_TEST_RESULT=1
+
+timeout 30 bash -c "until systemctl -q is-active systemd-journald@cat-test.service; do sleep .5; done"
+
+journalctl --namespace cat-test --grep "JOURNAL_STREAM="
+journalctl --namespace cat-test --grep "CAT_TEST_RESULT=1"
+
+systemctl disable --now systemd-journald@cat-test.socket
index 2123b10152893758f4141564c25e4785b04d901f..479011ea78f43b81d0c162f281f30357ea67ba06 100755 (executable)
@@ -6,11 +6,11 @@ set -o pipefail
 JOURNAL_DIR="$(mktemp -d)"
 REMOTE_OUT="$(mktemp -d)"
 # tar on C8S doesn't support the --zstd option
-unzstd --stdout "/test-journals/afl-corrupted-journals.tar.zst" | tar -xC "$JOURNAL_DIR/"
+unzstd --stdout "/usr/lib/systemd/tests/testdata/test-journals/afl-corrupted-journals.tar.zst" | tar -xC "$JOURNAL_DIR/"
 while read -r file; do
     filename="${file##*/}"
     unzstd "$file" -o "$JOURNAL_DIR/${filename%*.zst}"
-done < <(find /test-journals/corrupted/ -name "*.zst")
+done < <(find /usr/lib/systemd/tests/testdata/test-journals/corrupted/ -name "*.zst")
 # First, try each of them sequentially. Skip this part when running with plain
 # QEMU, as it is excruciatingly slow
 # Note: we care only about exit code 124 (timeout) and special bash exit codes
index 2c0c50f5b83efbc7d33e1e8ad5506cb5804afb33..90d865cdf571c74f4dbbe30015e7bad84ec49660 100755 (executable)
@@ -244,7 +244,7 @@ JOURNAL_DIR="$(mktemp -d)"
 while read -r file; do
     filename="${file##*/}"
     unzstd "$file" -o "$JOURNAL_DIR/${filename%*.zst}"
-done < <(find /test-journals/no-rtc -name "*.zst")
+done < <(find /usr/lib/systemd/tests/testdata/test-journals/no-rtc -name "*.zst")
 
 journalctl --directory="$JOURNAL_DIR" --list-boots --output=json >/tmp/lb1
 diff -u /tmp/lb1 - <<'EOF'
@@ -275,3 +275,11 @@ hello
 world
 EOF
 rm -f "$CURSOR_FILE"
+
+# Check that --until works with --after-cursor and --lines/-n
+# See: https://github.com/systemd/systemd/issues/31776
+CURSOR_FILE="$(mktemp)"
+journalctl -q -n 0 --cursor-file="$CURSOR_FILE"
+TIMESTAMP="$(journalctl -q -n 1 --cursor="$(<"$CURSOR_FILE")" --output=short-unix | cut -d ' ' -f 1 | cut -d '.' -f 1)"
+[[ -z "$(journalctl -q -n 10 --after-cursor="$(<"$CURSOR_FILE")" --until "@$((TIMESTAMP - 3))")" ]]
+rm -f "$CURSOR_FILE"
index e28a1562bf237a3aec702f6e7abf82b7875ebec1..4bf9922ef3aec57b7ac69206284c674827491673 100755 (executable)
@@ -181,13 +181,13 @@ checkblob() {
 }
 
 mkdir /tmp/blob1 /tmp/blob2
-echo data1 blob1 > /tmp/blob1/test1
-echo data1 blob2 > /tmp/blob2/test1
-echo data2 blob1 > /tmp/blob1/test2
-echo data2 blob2 > /tmp/blob2/test2
-echo invalid filename > /tmp/blob1/файл
-echo data3 > /tmp/external-test3
-echo avatardata > /tmp/external-avatar
+echo data1 blob1 >/tmp/blob1/test1
+echo data1 blob2 >/tmp/blob2/test1
+echo data2 blob1 >/tmp/blob1/test2
+echo data2 blob2 >/tmp/blob2/test2
+echo invalid filename >/tmp/blob1/файл
+echo data3 >/tmp/external-test3
+echo avatardata >/tmp/external-avatar
 ln -s /tmp/external-avatar /tmp/external-avatar-lnk
 dd if=/dev/urandom of=/tmp/external-barely-fits bs=1M count=64
 dd if=/dev/urandom of=/tmp/external-toobig bs=1M count=65
index a94776eadd1f6fb9541546b9f07e6f96f04044c4..4f3c967e2cf249617f1b5b6d995e1f1f3c6bf00f 100755 (executable)
@@ -231,15 +231,15 @@ assert_eq "$KVER" "$UNIT_KVER"
 umount /proc/version
 rm -f "$TMP_KVER"
 
-# Check that invoking the tool under the uid0 alias name works
-uid0 ls /
-assert_eq "$(uid0 echo foo)" "foo"
+# Check that invoking the tool under the run0 alias name works
+run0 ls /
+assert_eq "$(run0 echo foo)" "foo"
 # Check if we set some expected environment variables
 for arg in "" "--user=root" "--user=testuser"; do
-    assert_eq "$(uid0 ${arg:+"$arg"} bash -c 'echo $SUDO_USER')" "$USER"
-    assert_eq "$(uid0 ${arg:+"$arg"} bash -c 'echo $SUDO_UID')" "$(id -u "$USER")"
-    assert_eq "$(uid0 ${arg:+"$arg"} bash -c 'echo $SUDO_GID')" "$(id -u "$USER")"
+    assert_eq "$(run0 ${arg:+"$arg"} bash -c 'echo $SUDO_USER')" "$USER"
+    assert_eq "$(run0 ${arg:+"$arg"} bash -c 'echo $SUDO_UID')" "$(id -u "$USER")"
+    assert_eq "$(run0 ${arg:+"$arg"} bash -c 'echo $SUDO_GID')" "$(id -u "$USER")"
 done
-# Let's chain a couple of uid0 calls together, for fun
-readarray -t cmdline < <(printf "%.0suid0\n" {0..31})
+# Let's chain a couple of run0 calls together, for fun
+readarray -t cmdline < <(printf "%.0srun0\n" {0..31})
 assert_eq "$("${cmdline[@]}" bash -c 'echo $SUDO_USER')" "$USER"
index 819584dcbab0de5518b09f2a9e8317587c5ec47f..db95a58950d96649eaa3d5e6e6014cfbeb2eac85 100755 (executable)
@@ -36,6 +36,8 @@ def main():
     args = parser.parse_args()
 
     args.output.mkdir(exist_ok=True)
+    # Make sure we don't inherit any setgid/setuid bit or such.
+    args.output.chmod(mode=0o755)
     for exe in args.executables:
         extract_interfaces_xml(args.output, exe)
 
similarity index 67%
rename from tools/add-git-hook.sh
rename to tools/git-setup.sh
index 8cff62e864da9c9a1733b775d1743fe2aa7ca95c..4b49ab9c45f9d48547b93d3827038809b0550bfe 100755 (executable)
@@ -4,6 +4,12 @@ set -eu
 
 cd "${MESON_SOURCE_ROOT:?}"
 
+if [ -e .git ]; then
+    git config submodule.recurse true
+    git config fetch.recurseSubmodules on-demand
+    git config push.recurseSubmodules no
+fi
+
 if [ ! -f .git/hooks/pre-commit.sample ] || [ -f .git/hooks/pre-commit ]; then
     exit 2 # not needed
 fi
index 8f70cbe567d32d7920aacf1b16f00bc92f69135c..25aa8ec5106d5fe91b79d3f5cd76f2380a8e0d1d 100644 (file)
@@ -19,7 +19,7 @@ Before=rescue.service
 [Service]
 Environment=HOME=/root
 WorkingDirectory=-/root
-ExecStartPre=-{{BINDIR}}/plymouth --wait quit
+ExecStartPre=-plymouth --wait quit
 ExecStart=-{{LIBEXECDIR}}/systemd-sulogin-shell emergency
 Type=idle
 StandardInput=tty-force
index 1458cc5986765a91bc6e464b4dc4a953e9b62285..8808c5501c80077471b38e802bacb7eaed6b8d65 100644 (file)
@@ -203,6 +203,7 @@ units = [
         { 'file' : 'sockets.target' },
         { 'file' : 'soft-reboot.target' },
         { 'file' : 'sound.target' },
+        { 'file' : 'ssh-access.target' },
         {
           'file' : 'suspend-then-hibernate.target',
           'conditions' : ['ENABLE_HIBERNATE'],
@@ -272,7 +273,7 @@ units = [
           'conditions' : ['ENABLE_BOOTLOADER'],
         },
         {
-          'file' : 'systemd-bootctl@.service.in',
+          'file' : 'systemd-bootctl@.service',
           'conditions' : ['ENABLE_BOOTLOADER'],
         },
         {
@@ -575,7 +576,7 @@ units = [
         { 'file' : 'systemd-reboot.service' },
         { 'file' : 'systemd-remount-fs.service.in' },
         {
-          'file' : 'systemd-repart.service.in',
+          'file' : 'systemd-repart.service',
           'conditions' : ['ENABLE_REPART'],
           'symlinks' : ['sysinit.target.wants/', 'initrd-root-fs.target.wants/'],
         },
index 5113408942125188e8b23edfe41a260b75c00154..add604724a7e0176c4c2814407f70ea865af5eec 100644 (file)
@@ -18,7 +18,7 @@ Before=shutdown.target
 [Service]
 Environment=HOME=/root
 WorkingDirectory=-/root
-ExecStartPre=-{{BINDIR}}/plymouth --wait quit
+ExecStartPre=-plymouth --wait quit
 ExecStart=-{{LIBEXECDIR}}/systemd-sulogin-shell rescue
 Type=idle
 StandardInput=tty-force
diff --git a/units/ssh-access.target b/units/ssh-access.target
new file mode 100644 (file)
index 0000000..f9b6a4c
--- /dev/null
@@ -0,0 +1,12 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=SSH Access Available
+Documentation=man:systemd.special(7)
index 0f826041078a8735550dc8c98382c1e6f34b65e4..ee87118a074b033d80f9d34503cc018d5f56f1b7 100644 (file)
@@ -13,6 +13,7 @@ Documentation=man:systemd-battery-check.service(8)
 ConditionVirtualization=no
 ConditionDirectoryNotEmpty=/sys/class/power_supply/
 ConditionKernelCommandLine=!systemd.battery_check=0
+ConditionKernelCommandLine=!systemd.battery-check=0
 AssertPathExists=/etc/initrd-release
 DefaultDependencies=no
 After=plymouth-start.service
index 2b26d7edac08ca331cdb4b33bdfa64edbb5770c4..59151ba161c488a4e6f7696ffefd3bc2b36f93b9 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Boot Control (Varlink)
+Description=Boot Entries Service Socket
 Documentation=man:bootctl(1)
 DefaultDependencies=no
 After=local-fs.target
similarity index 88%
rename from units/systemd-bootctl@.service.in
rename to units/systemd-bootctl@.service
index d1c3deddfd7544b06687c7b18436bffc83dbbf47..5de61566380dd2f11c051782bdf820a53b64603c 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Boot Control (Varlink)
+Description=Boot Entries Service
 Documentation=man:bootctl(1)
 DefaultDependencies=no
 Conflicts=shutdown.target
@@ -17,4 +17,4 @@ Before=shutdown.target
 
 [Service]
 Environment=LISTEN_FDNAMES=varlink
-ExecStart={{BINDIR}}/bootctl
+ExecStart=bootctl
index 0f89b39c3e402d1eab335287b5367b198cb7650e..bf13c11e0fa905f997e3cf1883f043f4137ae38b 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Credential Encryption/Decryption (Varlink)
+Description=Credential Encryption/Decryption
 Documentation=man:systemd-creds(1)
 DefaultDependencies=no
 Before=sockets.target
index 37cdd319f64411f328a0b43187a6c2e07bcf2427..d565836d3ad8b546f98952aa99b50667477b2d54 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Credential Encryption/Decryption (Varlink)
+Description=Credential Encryption/Decryption
 Documentation=man:systemd-creds(1)
 DefaultDependencies=no
 Conflicts=shutdown.target initrd-switch-root.target
index 8d0a06c5f278d660db46624af2b0a45472858da1..2a2cfce6531667c23d7c33d87901fe3011060f79 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Hostname Service Varlink Socket
+Description=Hostname Service Socket
 Documentation=man:systemd-hostnamed.service(8)
 Documentation=man:hostname(5)
 Documentation=man:machine-info(5)
index 1e2178e8fdf784d8305ecde53585ffc401f88183..e2ffb96bfc62468519bb7c10f4d867f5b79c41eb 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Journal Socket
+Description=Journal Sockets
 Documentation=man:systemd-journald.service(8) man:journald.conf(5)
 DefaultDependencies=no
 Before=sockets.target
index 60c025fcc3b90d27f8ea5ec0e466ee80bd54e838..65813a5f6d7b8d71e2e030f0aa72ea0010eb1b36 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Journal Socket for Namespace %i
+Description=Journal Sockets for Namespace %i
 Documentation=man:systemd-journald.service(8) man:journald.conf(5)
 StopWhenUnneeded=yes
 
@@ -22,3 +22,6 @@ PassCredentials=yes
 PassSecurity=yes
 ReceiveBuffer=8M
 SendBuffer=8M
+
+[Install]
+WantedBy=sockets.target
index 0ad6cf3ab0188ec4876a371c3163b26343ac06db..97b9186f3b05a8f6b22c65125c333334906b9f0d 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Commit a transient machine-id on disk
+Description=Save Transient machine-id to Disk
 Documentation=man:systemd-machine-id-commit.service(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
index 0fe6740bdae158fa06f83f1b9098d608b5a91b5c..ad262fa13ab1e752c5b5889f7e31a05107467f9a 100644 (file)
@@ -20,7 +20,9 @@ ConditionDirectoryNotEmpty=|/usr/local/lib/modules-load.d
 ConditionDirectoryNotEmpty=|/etc/modules-load.d
 ConditionDirectoryNotEmpty=|/run/modules-load.d
 ConditionKernelCommandLine=|modules-load
+ConditionKernelCommandLine=|modules_load
 ConditionKernelCommandLine=|rd.modules-load
+ConditionKernelCommandLine=|rd.modules_load
 
 [Service]
 Type=oneshot
index bfbc0b193e143b368d643482ab0237c86533e628..6141fdbb6d78ab2570468a9cb6ead309aa942d12 100644 (file)
@@ -27,7 +27,6 @@ DeviceAllow=char-* rw
 ExecStart=!!{{LIBEXECDIR}}/systemd-networkd
 FileDescriptorStoreMax=512
 ImportCredential=network.wireguard.*
-InaccessiblePaths=-/boot -/efi
 LockPersonality=yes
 MemoryDenyWriteExecute=yes
 NoNewPrivileges=yes
@@ -37,7 +36,7 @@ ProtectControlGroups=yes
 ProtectHome=yes
 ProtectKernelLogs=yes
 ProtectKernelModules=yes
-ProtectSystem=full
+ProtectSystem=strict
 Restart=on-failure
 RestartKillSignal=SIGUSR2
 RestartSec=0
index 41db50acd881bf3fe5f502a0efea2705cb971752..4f7474812544024308fb8696e628e670cc8b0288 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=TPM2 PCR Extension (Varlink)
+Description=TPM PCR Measurements
 Documentation=man:systemd-pcrextend(8)
 DefaultDependencies=no
 After=tpm2.target
index 6020a21c40c7d04882068e13bd9343b825e2fcbc..68b71d40687e09363dc143f0a9118f07fe25f5ec 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=TPM2 PCR Extension (Varlink)
+Description=TPM PCR Measurements
 Documentation=man:systemd-pcrphase.service(8)
 DefaultDependencies=no
 After=tpm2.target
index 582e1d83e505e609d74a30401ebe5383fdc0c2cc..5b40a91ca649e3d0d95a4e5f26af9893e68a8723 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=TPM2 PCR Root File System Measurement
+Description=TPM PCR Root File System Measurement
 Documentation=man:systemd-pcrfs-root.service(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
index 262a82fb04ce41134a9f5702f1fc63b5d90578db..203d7b9782e1a3fb95d77ec21328d819734b60f8 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=TPM2 PCR File System Measurement of %f
+Description=TPM PCR File System Measurement of %f
 Documentation=man:systemd-pcrfs@.service(8)
 DefaultDependencies=no
 BindsTo=%i.mount
index dd0d358793fa88d8b991deb3d18b1dc5a5c00cf7..807ebc29f26ba277701159dbae08af8685a9ad52 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Lock File Systems to TPM2 PCR Policy
+Description=Lock File Systems to TPM PCR Policy
 Documentation=man:systemd-pcrlock(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
index b2716713939306631b763ca25d01220331b52429..cae8179bbfcc63747c41a70ae8f10bfc83f69487 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Lock Firmware Code to TPM2 PCR Policy
+Description=Lock Firmware Code to TPM PCR Policy
 Documentation=man:systemd-pcrlock(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
index 8440f5982b9c86368c3f80768121cef330f9ba71..74845044a2a75cdea3a42dc70c22080228a93a95 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Lock Firmware Configuration to TPM2 PCR Policy
+Description=Lock Firmware Configuration to TPM PCR Policy
 Documentation=man:systemd-pcrlock(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
index 16c6a99251f983a03a9c10c07b6265eefe4e89f1..c82c358149a80fa4176bb029bb2726c48b00a1d9 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Lock Machine ID to TPM2 PCR Policy
+Description=Lock Machine ID to TPM PCR Policy
 Documentation=man:systemd-pcrlock(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
index 444e1e49f11c10b8d2141cbfe7d8b6e111a9c767..4dd18ec0097abab42f1775369e1ce872628500ed 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Make TPM2 PCR Policy
+Description=Make TPM PCR Policy
 Documentation=man:systemd-pcrlock(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
index d5c722cf311880504172d02299004e1e28742a3b..9f6c1a4ef42778d41939abb4a37081cdd3838678 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Lock UEFI SecureBoot Authority to TPM2 PCR Policy
+Description=Lock UEFI SecureBoot Authority to TPM PCR Policy
 Documentation=man:systemd-pcrlock(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
index fc50e17aaa5006fc99dfaa0a7938f0bc3c52f4d7..0975aca5a268baff467800f485791fd6534479d2 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Lock UEFI SecureBoot Policy to TPM2 PCR Policy
+Description=Lock UEFI SecureBoot Policy to TPM PCR Policy
 Documentation=man:systemd-pcrlock(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
index 21431478b88bef3094570579aa4cd5162a63145d..17a56f7eb3e4267fe749486ed295a68fe9d53dd5 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Make TPM2 PCR Policy (Varlink)
+Description=Make TPM PCR Policy
 Documentation=man:systemd-pcrlock(8)
 DefaultDependencies=no
 After=tpm2.target
index 50a0a3de8eb731c562a15c2966ac6b2cfacc0e17..3528c565c8a29d7848b6af60601450ffda767cb9 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=Make TPM2 PCR Policy (Varlink)
+Description=Make TPM PCR Policy
 Documentation=man:systemd-pcrlock(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
index cbd1005104f2f26bcfe24602c2769f30baf884a2..65caf2ed49280af18bc4b5d1dd11704c0ad21a29 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=TPM2 PCR Machine ID Measurement
+Description=TPM PCR Machine ID Measurement
 Documentation=man:systemd-pcrmachine.service(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
index 3b18b4f29d60c39f81176dd780e9b88683cb5356..6fcf94de76c5f2754d8ea584323147acf8a7dd99 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=TPM2 PCR Barrier (initrd)
+Description=TPM PCR Barrier (initrd)
 Documentation=man:systemd-pcrphase-initrd.service(8)
 DefaultDependencies=no
 Conflicts=shutdown.target initrd-switch-root.target
index d938e02401bb70ae457087547eb7ec9afc46e731..8c0c0c82a2c7b26c8750e6cf9b64d3a4914dc561 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=TPM2 PCR Barrier (Initialization)
+Description=TPM PCR Barrier (Initialization)
 Documentation=man:systemd-pcrphase-sysinit.service(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
index 26b9e5c5389114cb26f1cadb20a448d90d1459c0..04ace12e14d4eecfbfd9461e5d947c4178b18b70 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=TPM2 PCR Barrier (User)
+Description=TPM PCR Barrier (User)
 Documentation=man:systemd-pcrphase.service(8)
 After=remote-fs.target remote-cryptsetup.target tpm2.target
 Before=systemd-user-sessions.service
similarity index 96%
rename from units/systemd-repart.service.in
rename to units/systemd-repart.service
index 2b57b93ca874878575af15138a826449dac4f705..5c9e6fb8b1ff3084b65a41a134bebf671deaa7d5 100644 (file)
@@ -29,7 +29,7 @@ Before=shutdown.target initrd-switch-root.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{BINDIR}}/systemd-repart --dry-run=no
+ExecStart=systemd-repart --dry-run=no
 
 # The tool returns 76 if it can't find the root block device
 SuccessExitStatus=76
index 1a616ca69ca4293d99d3da1d894008d2d8f7f553..78475cf1967ff813bd186a6f1580ab8767a216d0 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=System Extension Image Management (Varlink)
+Description=System Extension Image Management
 Documentation=man:systemd-sysext(8)
 DefaultDependencies=no
 After=local-fs.target
index 544e22fe0425dc5c6f755113a320b0b2fecb502a..9dcbf9f1dd85143f291197c4e29b6a821fded557 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=System Extension Image Management (Varlink)
+Description=System Extension Image Management
 Documentation=man:systemd-sysext(8)
 DefaultDependencies=no
 After=local-fs.target
index 628f8166782b8d0845979928a236c12d8b851a54..9574ffd2895fe98d103b1f5848b2eb015a037342 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=TPM2 SRK Setup (Early)
+Description=Early TPM SRK Setup
 Documentation=man:systemd-tpm2-setup.service(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
@@ -20,4 +20,4 @@ After=tpm2.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-tpm2-setup --early=yes
+ExecStart={{LIBEXECDIR}}/systemd-tpm2-setup --early=yes --graceful
index 4830afa24356c8e5300f1e9ec074ac87ed38d1a6..df6860670aef736368527947d211912b417ff6b9 100644 (file)
@@ -8,7 +8,7 @@
 #  (at your option) any later version.
 
 [Unit]
-Description=TPM2 SRK Setup
+Description=TPM SRK Setup
 Documentation=man:systemd-tpm2-setup.service(8)
 DefaultDependencies=no
 Conflicts=shutdown.target
@@ -22,4 +22,4 @@ After=tpm2.target
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStart={{LIBEXECDIR}}/systemd-tpm2-setup
+ExecStart={{LIBEXECDIR}}/systemd-tpm2-setup --graceful