summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/activate/activate.c3
-rw-r--r--src/analyze/analyze-verify.c8
-rw-r--r--src/analyze/analyze.c4
-rw-r--r--src/backlight/backlight.c3
-rw-r--r--src/basic/alloc-util.c81
-rw-r--r--src/basic/alloc-util.h108
-rw-r--r--src/basic/audit-util.c (renamed from src/basic/audit.c)4
-rw-r--r--src/basic/audit-util.h (renamed from src/basic/audit.h)0
-rw-r--r--src/basic/bitmap.c4
-rw-r--r--src/basic/btrfs-util.c10
-rw-r--r--src/basic/bus-label.c7
-rw-r--r--src/basic/calendarspec.c2
-rw-r--r--src/basic/cap-list.c3
-rw-r--r--src/basic/capability-util.c (renamed from src/basic/capability.c)4
-rw-r--r--src/basic/capability-util.h (renamed from src/basic/capability.h)0
-rw-r--r--src/basic/cgroup-util.c7
-rw-r--r--src/basic/chattr-util.c107
-rw-r--r--src/basic/chattr-util.h28
-rw-r--r--src/basic/conf-files.c1
-rw-r--r--src/basic/copy.c7
-rw-r--r--src/basic/cpu-set-util.c32
-rw-r--r--src/basic/device-nodes.h2
-rw-r--r--src/basic/dirent-util.c81
-rw-r--r--src/basic/dirent-util.h51
-rw-r--r--src/basic/env-util.c14
-rw-r--r--src/basic/env-util.h2
-rw-r--r--src/basic/escape.c5
-rw-r--r--src/basic/extract-word.c1
-rw-r--r--src/basic/fd-util.c30
-rw-r--r--src/basic/fd-util.h2
-rw-r--r--src/basic/fdset.c4
-rw-r--r--src/basic/fdset.h2
-rw-r--r--src/basic/fileio.c305
-rw-r--r--src/basic/fileio.h28
-rw-r--r--src/basic/fs-util.c480
-rw-r--r--src/basic/fs-util.h74
-rw-r--r--src/basic/glob-util.c71
-rw-r--r--src/basic/glob-util.h37
-rw-r--r--src/basic/hashmap.c12
-rw-r--r--src/basic/hexdecoct.c698
-rw-r--r--src/basic/hexdecoct.h54
-rw-r--r--src/basic/hostname-util.c1
-rw-r--r--src/basic/in-addr-util.c1
-rw-r--r--src/basic/io-util.h39
-rw-r--r--src/basic/json.c4
-rw-r--r--src/basic/locale-util.c87
-rw-r--r--src/basic/locale-util.h21
-rw-r--r--src/basic/lockfile-util.c3
-rw-r--r--src/basic/log.c7
-rw-r--r--src/basic/macro.h122
-rw-r--r--src/basic/memfd-util.c1
-rw-r--r--src/basic/mkdir.c7
-rw-r--r--src/basic/mount-util.c529
-rw-r--r--src/basic/mount-util.h52
-rw-r--r--src/basic/parse-util.c447
-rw-r--r--src/basic/parse-util.h91
-rw-r--r--src/basic/path-util.c421
-rw-r--r--src/basic/path-util.h18
-rw-r--r--src/basic/prioq.c3
-rw-r--r--src/basic/proc-cmdline.c145
-rw-r--r--src/basic/proc-cmdline.h28
-rw-r--r--src/basic/process-util.c176
-rw-r--r--src/basic/process-util.h33
-rw-r--r--src/basic/replace-var.c1
-rw-r--r--src/basic/rlimit-util.c70
-rw-r--r--src/basic/rlimit-util.h33
-rw-r--r--src/basic/rm-rf.c2
-rw-r--r--src/basic/selinux-util.c1
-rw-r--r--src/basic/signal-util.c9
-rw-r--r--src/basic/signal-util.h2
-rw-r--r--src/basic/smack-util.c9
-rw-r--r--src/basic/socket-label.c1
-rw-r--r--src/basic/socket-util.c4
-rw-r--r--src/basic/socket-util.h3
-rw-r--r--src/basic/stat-util.c216
-rw-r--r--src/basic/stat-util.h70
-rw-r--r--src/basic/stdio-util.h78
-rw-r--r--src/basic/strbuf.c3
-rw-r--r--src/basic/string-table.c35
-rw-r--r--src/basic/string-table.h88
-rw-r--r--src/basic/string-util.c18
-rw-r--r--src/basic/string-util.h2
-rw-r--r--src/basic/strv.c1
-rw-r--r--src/basic/syslog-util.c115
-rw-r--r--src/basic/syslog-util.h34
-rw-r--r--src/basic/terminal-util.c82
-rw-r--r--src/basic/terminal-util.h3
-rw-r--r--src/basic/time-util.c3
-rw-r--r--src/basic/umask-util.h48
-rw-r--r--src/basic/unit-name.c5
-rw-r--r--src/basic/user-util.c49
-rw-r--r--src/basic/user-util.h13
-rw-r--r--src/basic/utf8.c2
-rw-r--r--src/basic/util.c3434
-rw-r--r--src/basic/util.h538
-rw-r--r--src/basic/virt.c13
-rw-r--r--src/basic/virt.h2
-rw-r--r--src/basic/web-util.c78
-rw-r--r--src/basic/web-util.h32
-rw-r--r--src/basic/xattr-util.c195
-rw-r--r--src/basic/xattr-util.h38
-rw-r--r--src/binfmt/binfmt.c1
-rw-r--r--src/boot/bootctl.c3
-rw-r--r--src/bootchart/bootchart.c2
-rw-r--r--src/bootchart/store.c3
-rw-r--r--src/bootchart/svg.c1
-rw-r--r--src/bus-proxyd/bus-proxyd.c3
-rw-r--r--src/bus-proxyd/bus-xml-policy.c3
-rw-r--r--src/bus-proxyd/driver.c1
-rw-r--r--src/bus-proxyd/proxy.c2
-rw-r--r--src/bus-proxyd/stdio-bridge.c1
-rw-r--r--src/bus-proxyd/test-bus-xml-policy.c1
-rw-r--r--src/cgls/cgls.c1
-rw-r--r--src/cgtop/cgtop.c2
-rw-r--r--src/core/automount.c48
-rw-r--r--src/core/bus-endpoint.c5
-rw-r--r--src/core/bus-policy.c2
-rw-r--r--src/core/busname.c11
-rw-r--r--src/core/cgroup.c7
-rw-r--r--src/core/dbus-cgroup.c2
-rw-r--r--src/core/dbus-execute.c14
-rw-r--r--src/core/dbus-job.c3
-rw-r--r--src/core/dbus-manager.c4
-rw-r--r--src/core/dbus-scope.c15
-rw-r--r--src/core/dbus-service.c2
-rw-r--r--src/core/dbus-socket.c3
-rw-r--r--src/core/dbus-timer.c7
-rw-r--r--src/core/dbus-unit.c5
-rw-r--r--src/core/dbus.c4
-rw-r--r--src/core/device.c5
-rw-r--r--src/core/execute.c9
-rw-r--r--src/core/failure-action.c5
-rw-r--r--src/core/hostname-setup.c1
-rw-r--r--src/core/ima-setup.c1
-rw-r--r--src/core/job.c5
-rw-r--r--src/core/kill.c5
-rw-r--r--src/core/killall.c2
-rw-r--r--src/core/kmod-setup.c2
-rw-r--r--src/core/load-fragment.c42
-rw-r--r--src/core/machine-id-setup.c6
-rw-r--r--src/core/main.c9
-rw-r--r--src/core/manager.c183
-rw-r--r--src/core/mount-setup.c23
-rw-r--r--src/core/mount.c38
-rw-r--r--src/core/namespace.c5
-rw-r--r--src/core/path.c4
-rw-r--r--src/core/scope.c4
-rw-r--r--src/core/selinux-access.c9
-rw-r--r--src/core/service.c103
-rw-r--r--src/core/show-status.c85
-rw-r--r--src/core/show-status.h7
-rw-r--r--src/core/shutdown.c2
-rw-r--r--src/core/slice.c1
-rw-r--r--src/core/smack-setup.c2
-rw-r--r--src/core/snapshot.c5
-rw-r--r--src/core/snapshot.h2
-rw-r--r--src/core/socket.c17
-rw-r--r--src/core/swap.c24
-rw-r--r--src/core/timer.c4
-rw-r--r--src/core/transaction.c3
-rw-r--r--src/core/umount.c1
-rw-r--r--src/core/unit-printf.c1
-rw-r--r--src/core/unit.c12
-rw-r--r--src/cryptsetup/cryptsetup-generator.c4
-rw-r--r--src/cryptsetup/cryptsetup.c3
-rw-r--r--src/dbus1-generator/dbus1-generator.c3
-rw-r--r--src/debug-generator/debug-generator.c9
-rw-r--r--src/delta/delta.c6
-rw-r--r--src/detect-virt/detect-virt.c22
-rw-r--r--src/escape/escape.c1
-rw-r--r--src/firstboot/firstboot.c11
-rw-r--r--src/fsck/fsck.c5
-rw-r--r--src/fstab-generator/fstab-generator.c6
-rw-r--r--src/getty-generator/getty-generator.c1
-rw-r--r--src/gpt-auto-generator/gpt-auto-generator.c6
-rw-r--r--src/hibernate-resume/hibernate-resume-generator.c3
-rw-r--r--src/hibernate-resume/hibernate-resume.c3
-rw-r--r--src/hostname/hostnamectl.c1
-rw-r--r--src/hostname/hostnamed.c16
-rw-r--r--src/hwdb/hwdb.c5
-rw-r--r--src/import/curl-util.c1
-rw-r--r--src/import/export-raw.c2
-rw-r--r--src/import/export-tar.c2
-rw-r--r--src/import/export.c2
-rw-r--r--src/import/import-common.c2
-rw-r--r--src/import/import-compress.c3
-rw-r--r--src/import/import-raw.c4
-rw-r--r--src/import/import-tar.c3
-rw-r--r--src/import/import.c2
-rw-r--r--src/import/importd.c6
-rw-r--r--src/import/pull-common.c6
-rw-r--r--src/import/pull-dkr.c12
-rw-r--r--src/import/pull-job.c4
-rw-r--r--src/import/pull-raw.c5
-rw-r--r--src/import/pull-tar.c4
-rw-r--r--src/import/pull.c3
-rw-r--r--src/import/qcow2-util.c7
-rw-r--r--src/initctl/initctl.c1
-rw-r--r--src/journal-remote/journal-gatewayd.c2
-rw-r--r--src/journal-remote/journal-remote-parse.c2
-rw-r--r--src/journal-remote/journal-remote-write.c1
-rw-r--r--src/journal-remote/journal-remote.c27
-rw-r--r--src/journal-remote/journal-upload-journal.c26
-rw-r--r--src/journal-remote/journal-upload.c3
-rw-r--r--src/journal-remote/microhttpd-util.c1
-rw-r--r--src/journal/cat.c2
-rw-r--r--src/journal/catalog.c3
-rw-r--r--src/journal/compress.c2
-rw-r--r--src/journal/coredump-vacuum.c2
-rw-r--r--src/journal/coredump.c8
-rw-r--r--src/journal/coredumpctl.c5
-rw-r--r--src/journal/fsprg.h1
-rw-r--r--src/journal/journal-authenticate.c1
-rw-r--r--src/journal/journal-file.c4
-rw-r--r--src/journal/journal-send.c3
-rw-r--r--src/journal/journal-vacuum.c4
-rw-r--r--src/journal/journal-verify.c2
-rw-r--r--src/journal/journalctl.c8
-rw-r--r--src/journal/journald-audit.c3
-rw-r--r--src/journal/journald-console.c10
-rw-r--r--src/journal/journald-kmsg.c3
-rw-r--r--src/journal/journald-native.c4
-rw-r--r--src/journal/journald-rate-limit.c1
-rw-r--r--src/journal/journald-server.c138
-rw-r--r--src/journal/journald-server.h17
-rw-r--r--src/journal/journald-stream.c74
-rw-r--r--src/journal/journald-stream.h4
-rw-r--r--src/journal/journald-syslog.c4
-rw-r--r--src/journal/journald-wall.c1
-rw-r--r--src/journal/journald.c8
-rw-r--r--src/journal/mmap-cache.c1
-rw-r--r--src/journal/sd-journal.c26
-rw-r--r--src/journal/stacktrace.c1
-rw-r--r--src/journal/test-catalog.c2
-rw-r--r--src/journal/test-compress-benchmark.c2
-rw-r--r--src/journal/test-compress.c2
-rw-r--r--src/journal/test-journal-flush.c1
-rw-r--r--src/journal/test-journal-init.c1
-rw-r--r--src/journal/test-journal-interleaving.c5
-rw-r--r--src/journal/test-journal-match.c1
-rw-r--r--src/journal/test-journal-stream.c11
-rw-r--r--src/journal/test-journal-syslog.c1
-rw-r--r--src/journal/test-mmap-cache.c3
-rw-r--r--src/libsystemd-network/dhcp6-option.c10
-rw-r--r--src/libsystemd-network/lldp-internal.c1
-rw-r--r--src/libsystemd-network/lldp-port.c1
-rw-r--r--src/libsystemd-network/lldp-tlv.c3
-rw-r--r--src/libsystemd-network/network-internal.c5
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c1
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c3
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c1
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c2
-rw-r--r--src/libsystemd-network/sd-dhcp6-lease.c6
-rw-r--r--src/libsystemd-network/sd-ipv4acd.c1
-rw-r--r--src/libsystemd-network/sd-ipv4ll.c1
-rw-r--r--src/libsystemd-network/sd-lldp.c2
-rw-r--r--src/libsystemd-network/sd-ndisc.c1
-rw-r--r--src/libsystemd-network/sd-pppoe.c1
-rw-r--r--src/libsystemd-network/test-dhcp-client.c1
-rw-r--r--src/libsystemd-network/test-dhcp-option.c8
-rw-r--r--src/libsystemd-network/test-ipv4ll-manual.c2
-rw-r--r--src/libsystemd-network/test-lldp.c1
-rw-r--r--src/libsystemd/sd-bus/bus-control.c7
-rw-r--r--src/libsystemd/sd-bus/bus-creds.c8
-rw-r--r--src/libsystemd/sd-bus/bus-dump.c7
-rw-r--r--src/libsystemd/sd-bus/bus-error.c1
-rw-r--r--src/libsystemd/sd-bus/bus-internal.c2
-rw-r--r--src/libsystemd/sd-bus/bus-introspect.c1
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.c5
-rw-r--r--src/libsystemd/sd-bus/bus-match.c3
-rw-r--r--src/libsystemd/sd-bus/bus-message.c2
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c1
-rw-r--r--src/libsystemd/sd-bus/bus-slot.c1
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c3
-rw-r--r--src/libsystemd/sd-bus/bus-track.c1
-rw-r--r--src/libsystemd/sd-bus/busctl-introspect.c3
-rw-r--r--src/libsystemd/sd-bus/busctl.c3
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c3
-rw-r--r--src/libsystemd/sd-bus/test-bus-benchmark.c1
-rw-r--r--src/libsystemd/sd-bus/test-bus-chat.c1
-rw-r--r--src/libsystemd/sd-bus/test-bus-gvariant.c1
-rw-r--r--src/libsystemd/sd-bus/test-bus-kernel-bloom.c1
-rw-r--r--src/libsystemd/sd-bus/test-bus-kernel.c1
-rw-r--r--src/libsystemd/sd-bus/test-bus-marshal.c2
-rw-r--r--src/libsystemd/sd-bus/test-bus-objects.c1
-rw-r--r--src/libsystemd/sd-bus/test-bus-proxy.c1
-rw-r--r--src/libsystemd/sd-bus/test-bus-zero-copy.c1
-rw-r--r--src/libsystemd/sd-daemon/sd-daemon.c12
-rw-r--r--src/libsystemd/sd-device/device-enumerator.c2
-rw-r--r--src/libsystemd/sd-device/device-private.c5
-rw-r--r--src/libsystemd/sd-device/sd-device.c4
-rw-r--r--src/libsystemd/sd-event/sd-event.c1
-rw-r--r--src/libsystemd/sd-hwdb/sd-hwdb.c1
-rw-r--r--src/libsystemd/sd-id128/sd-id128.c1
-rw-r--r--src/libsystemd/sd-login/sd-login.c5
-rw-r--r--src/libsystemd/sd-login/test-login.c1
-rw-r--r--src/libsystemd/sd-netlink/local-addresses.c2
-rw-r--r--src/libsystemd/sd-netlink/netlink-message.c1
-rw-r--r--src/libsystemd/sd-netlink/netlink-socket.c1
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.c7
-rw-r--r--src/libsystemd/sd-netlink/sd-netlink.c1
-rw-r--r--src/libsystemd/sd-netlink/test-local-addresses.c1
-rw-r--r--src/libsystemd/sd-network/network-util.c1
-rw-r--r--src/libsystemd/sd-network/sd-network.c5
-rw-r--r--src/libsystemd/sd-path/sd-path.c2
-rw-r--r--src/libsystemd/sd-resolve/sd-resolve.c1
-rw-r--r--src/libsystemd/sd-resolve/test-resolve.c1
-rw-r--r--src/libudev/libudev-device.c2
-rw-r--r--src/libudev/libudev-enumerate.c1
-rw-r--r--src/libudev/libudev-hwdb.c1
-rw-r--r--src/libudev/libudev-list.c5
-rw-r--r--src/libudev/libudev-monitor.c3
-rw-r--r--src/libudev/libudev-queue.c1
-rw-r--r--src/libudev/libudev-util.c1
-rw-r--r--src/libudev/libudev.c1
-rw-r--r--src/locale/localed.c21
-rw-r--r--src/login/inhibit.c1
-rw-r--r--src/login/loginctl.c2
-rw-r--r--src/login/logind-acl.c2
-rw-r--r--src/login/logind-action.c12
-rw-r--r--src/login/logind-button.c1
-rw-r--r--src/login/logind-core.c1
-rw-r--r--src/login/logind-dbus.c5
-rw-r--r--src/login/logind-device.c3
-rw-r--r--src/login/logind-inhibit.c3
-rw-r--r--src/login/logind-seat-dbus.c10
-rw-r--r--src/login/logind-seat.c3
-rw-r--r--src/login/logind-session-dbus.c1
-rw-r--r--src/login/logind-session-device.c1
-rw-r--r--src/login/logind-session.c5
-rw-r--r--src/login/logind-user-dbus.c1
-rw-r--r--src/login/logind-user.c6
-rw-r--r--src/login/logind-utmp.c3
-rw-r--r--src/login/logind.c2
-rw-r--r--src/login/pam_systemd.c4
-rw-r--r--src/login/sysfs-show.c2
-rw-r--r--src/machine/image-dbus.c6
-rw-r--r--src/machine/machine-dbus.c3
-rw-r--r--src/machine/machine.c25
-rw-r--r--src/machine/machinectl.c3
-rw-r--r--src/machine/machined-dbus.c2
-rw-r--r--src/machine/machined.c2
-rw-r--r--src/modules-load/modules-load.c2
-rw-r--r--src/network/networkctl.c5
-rw-r--r--src/network/networkd-address-pool.c1
-rw-r--r--src/network/networkd-address.c4
-rw-r--r--src/network/networkd-dhcp4.c5
-rw-r--r--src/network/networkd-fdb.c6
-rw-r--r--src/network/networkd-link-bus.c4
-rw-r--r--src/network/networkd-link.c9
-rw-r--r--src/network/networkd-manager-bus.c2
-rw-r--r--src/network/networkd-manager.c2
-rw-r--r--src/network/networkd-netdev-bond.c4
-rw-r--r--src/network/networkd-netdev-ipvlan.c3
-rw-r--r--src/network/networkd-netdev-macvlan.c3
-rw-r--r--src/network/networkd-netdev-tunnel.c4
-rw-r--r--src/network/networkd-netdev-tuntap.c1
-rw-r--r--src/network/networkd-netdev.c3
-rw-r--r--src/network/networkd-network-bus.c1
-rw-r--r--src/network/networkd-network.c4
-rw-r--r--src/network/networkd-route.c4
-rw-r--r--src/network/networkd-util.c2
-rw-r--r--src/network/networkd-wait-online-link.c1
-rw-r--r--src/network/networkd-wait-online-manager.c5
-rw-r--r--src/network/networkd.c2
-rw-r--r--src/network/test-network.c1
-rw-r--r--src/notify/notify.c2
-rw-r--r--src/nspawn/nspawn-cgroup.c1
-rw-r--r--src/nspawn/nspawn-expose-ports.c2
-rw-r--r--src/nspawn/nspawn-mount.c8
-rw-r--r--src/nspawn/nspawn-network.c1
-rw-r--r--src/nspawn/nspawn-register.c8
-rw-r--r--src/nspawn/nspawn-settings.c9
-rw-r--r--src/nspawn/nspawn-setuid.c1
-rw-r--r--src/nspawn/nspawn.c28
-rw-r--r--src/nss-myhostname/nss-myhostname.c1
-rw-r--r--src/nss-mymachines/nss-mymachines.c1
-rw-r--r--src/path/path.c1
-rw-r--r--src/quotacheck/quotacheck.c1
-rw-r--r--src/random-seed/random-seed.c1
-rw-r--r--src/rc-local-generator/rc-local-generator.c1
-rw-r--r--src/remount-fs/remount-fs.c7
-rw-r--r--src/resolve-host/resolve-host.c2
-rw-r--r--src/resolve/resolved-bus.c2
-rw-r--r--src/resolve/resolved-conf.c24
-rw-r--r--src/resolve/resolved-dns-answer.c1
-rw-r--r--src/resolve/resolved-dns-cache.c1
-rw-r--r--src/resolve/resolved-dns-packet.c10
-rw-r--r--src/resolve/resolved-dns-query.c4
-rw-r--r--src/resolve/resolved-dns-question.c3
-rw-r--r--src/resolve/resolved-dns-rr.c4
-rw-r--r--src/resolve/resolved-dns-scope.c1
-rw-r--r--src/resolve/resolved-dns-server.c4
-rw-r--r--src/resolve/resolved-dns-stream.c2
-rw-r--r--src/resolve/resolved-dns-transaction.c3
-rw-r--r--src/resolve/resolved-dns-zone.c1
-rw-r--r--src/resolve/resolved-link.c2
-rw-r--r--src/resolve/resolved-manager.c3
-rw-r--r--src/resolve/resolved.c2
-rw-r--r--src/rfkill/rfkill.c4
-rw-r--r--src/run/run.c2
-rw-r--r--src/shared/acl-util.c1
-rw-r--r--src/shared/acpi-fpdt.c1
-rw-r--r--src/shared/apparmor-util.c7
-rw-r--r--src/shared/architecture.c1
-rw-r--r--src/shared/ask-password-api.c3
-rw-r--r--src/shared/base-filesystem.c7
-rw-r--r--src/shared/bus-util.c10
-rw-r--r--src/shared/cgroup-show.c2
-rw-r--r--src/shared/clean-ipc.c2
-rw-r--r--src/shared/condition.c9
-rw-r--r--src/shared/conf-parser.c9
-rw-r--r--src/shared/dev-setup.c6
-rw-r--r--src/shared/dns-domain.c5
-rw-r--r--src/shared/dropin.c2
-rw-r--r--src/shared/efivars.c4
-rw-r--r--src/shared/firewall-util.c3
-rw-r--r--src/shared/fstab-util.c63
-rw-r--r--src/shared/fstab-util.h7
-rw-r--r--src/shared/generator.c2
-rw-r--r--src/shared/import-util.c5
-rw-r--r--src/shared/install-printf.c1
-rw-r--r--src/shared/install.c35
-rw-r--r--src/shared/logs-show.c3
-rw-r--r--src/shared/machine-image.c6
-rw-r--r--src/shared/machine-pool.c6
-rw-r--r--src/shared/pager.c1
-rw-r--r--src/shared/path-lookup.c1
-rw-r--r--src/shared/ptyfwd.c2
-rw-r--r--src/shared/sleep-config.c2
-rw-r--r--src/shared/spawn-polkit-agent.c6
-rw-r--r--src/shared/specifier.c3
-rw-r--r--src/shared/switch-root.c1
-rw-r--r--src/shared/utmp-wtmp.c1
-rw-r--r--src/socket-proxy/socket-proxyd.c1
-rw-r--r--src/system-update-generator/system-update-generator.c1
-rw-r--r--src/systemctl/systemctl.c72
-rw-r--r--src/sysusers/sysusers.c3
-rw-r--r--src/sysv-generator/sysv-generator.c479
-rw-r--r--src/test/test-async.c3
-rw-r--r--src/test/test-btrfs.c1
-rw-r--r--src/test/test-calendarspec.c1
-rw-r--r--src/test/test-cap-list.c11
-rw-r--r--src/test/test-capability.c2
-rw-r--r--src/test/test-cgroup-util.c4
-rw-r--r--src/test/test-condition.c3
-rw-r--r--src/test/test-conf-files.c3
-rw-r--r--src/test/test-copy.c2
-rw-r--r--src/test/test-date.c3
-rw-r--r--src/test/test-device-nodes.c1
-rw-r--r--src/test/test-dns-domain.c1
-rw-r--r--src/test/test-ellipsize.c1
-rw-r--r--src/test/test-execute.c95
-rw-r--r--src/test/test-extract-word.c546
-rw-r--r--src/test/test-fdset.c1
-rw-r--r--src/test/test-fileio.c2
-rw-r--r--src/test/test-fstab-util.c1
-rw-r--r--src/test/test-hashmap-plain.c1
-rw-r--r--src/test/test-hostname-util.c3
-rw-r--r--src/test/test-id128.c1
-rw-r--r--src/test/test-json.c1
-rw-r--r--src/test/test-namespace.c1
-rw-r--r--src/test/test-parse-util.c452
-rw-r--r--src/test/test-path-lookup.c21
-rw-r--r--src/test/test-path-util.c16
-rw-r--r--src/test/test-path.c6
-rw-r--r--src/test/test-prioq.c5
-rw-r--r--src/test/test-process-util.c3
-rw-r--r--src/test/test-socket-util.c1
-rw-r--r--src/test/test-strv.c1
-rw-r--r--src/test/test-tables.c13
-rw-r--r--src/test/test-terminal-util.c7
-rw-r--r--src/test/test-tmpfiles.c2
-rw-r--r--src/test/test-udev.c1
-rw-r--r--src/test/test-uid-range.c4
-rw-r--r--src/test/test-unit-file.c54
-rw-r--r--src/test/test-unit-name.c1
-rw-r--r--src/test/test-user-util.c1
-rw-r--r--src/test/test-utf8.c1
-rw-r--r--src/test/test-util.c827
-rw-r--r--src/test/test-xml.c1
-rw-r--r--src/timedate/timedatectl.c1
-rw-r--r--src/timedate/timedated.c23
-rw-r--r--src/timesync/timesyncd-conf.c19
-rw-r--r--src/timesync/timesyncd-manager.c2
-rw-r--r--src/timesync/timesyncd-server.c1
-rw-r--r--src/timesync/timesyncd.c3
-rw-r--r--src/tmpfiles/tmpfiles.c13
-rw-r--r--src/tty-ask-password-agent/tty-ask-password-agent.c2
-rw-r--r--src/udev/collect/collect.c1
-rw-r--r--src/udev/net/ethtool-util.c8
-rw-r--r--src/udev/net/link-config.c5
-rw-r--r--src/udev/udev-builtin-blkid.c1
-rw-r--r--src/udev/udev-builtin-hwdb.c1
-rw-r--r--src/udev/udev-builtin-keyboard.c2
-rw-r--r--src/udev/udev-builtin-net_setup_link.c3
-rw-r--r--src/udev/udev-builtin-path_id.c1
-rw-r--r--src/udev/udev-builtin-usb_id.c1
-rw-r--r--src/udev/udev-ctrl.c1
-rw-r--r--src/udev/udev-event.c1
-rw-r--r--src/udev/udev-node.c1
-rw-r--r--src/udev/udev-rules.c3
-rw-r--r--src/udev/udevadm-hwdb.c3
-rw-r--r--src/udev/udevadm-settle.c1
-rw-r--r--src/udev/udevd.c6
-rw-r--r--src/update-utmp/update-utmp.c11
-rw-r--r--src/vconsole/vconsole-setup.c2
507 files changed, 8776 insertions, 6086 deletions
diff --git a/src/activate/activate.c b/src/activate/activate.c
index 0e6ead310e..b7e6255f49 100644
--- a/src/activate/activate.c
+++ b/src/activate/activate.c
@@ -28,13 +28,14 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
+#include "fd-util.h"
#include "log.h"
#include "macro.h"
#include "signal-util.h"
#include "socket-util.h"
#include "string-util.h"
#include "strv.h"
-#include "fd-util.h"
static char** arg_listen = NULL;
static bool arg_accept = false;
diff --git a/src/analyze/analyze-verify.c b/src/analyze/analyze-verify.c
index f4255f979e..a377996a37 100644
--- a/src/analyze/analyze-verify.c
+++ b/src/analyze/analyze-verify.c
@@ -21,12 +21,14 @@
#include <stdlib.h>
-#include "manager.h"
+#include "alloc-util.h"
+#include "analyze-verify.h"
#include "bus-util.h"
#include "log.h"
-#include "strv.h"
+#include "manager.h"
#include "pager.h"
-#include "analyze-verify.h"
+#include "path-util.h"
+#include "strv.h"
static int generate_path(char **var, char **filenames) {
char **filename;
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 4bf83eb329..27ead903e9 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -27,12 +27,16 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "analyze-verify.h"
#include "bus-error.h"
#include "bus-util.h"
+#include "glob-util.h"
#include "hashmap.h"
+#include "locale-util.h"
#include "log.h"
#include "pager.h"
+#include "parse-util.h"
#include "special.h"
#include "strv.h"
#include "strxcpyx.h"
diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c
index fc96eee6a9..08980fba82 100644
--- a/src/backlight/backlight.c
+++ b/src/backlight/backlight.c
@@ -21,10 +21,13 @@
#include "libudev.h"
+#include "alloc-util.h"
#include "def.h"
#include "escape.h"
#include "fileio.h"
#include "mkdir.h"
+#include "parse-util.h"
+#include "proc-cmdline.h"
#include "string-util.h"
#include "udev-util.h"
#include "util.h"
diff --git a/src/basic/alloc-util.c b/src/basic/alloc-util.c
new file mode 100644
index 0000000000..48183e381f
--- /dev/null
+++ b/src/basic/alloc-util.c
@@ -0,0 +1,81 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "util.h"
+
+void* memdup(const void *p, size_t l) {
+ void *r;
+
+ assert(p);
+
+ r = malloc(l);
+ if (!r)
+ return NULL;
+
+ memcpy(r, p, l);
+ return r;
+}
+
+void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
+ size_t a, newalloc;
+ void *q;
+
+ assert(p);
+ assert(allocated);
+
+ if (*allocated >= need)
+ return *p;
+
+ newalloc = MAX(need * 2, 64u / size);
+ a = newalloc * size;
+
+ /* check for overflows */
+ if (a < size * need)
+ return NULL;
+
+ q = realloc(*p, a);
+ if (!q)
+ return NULL;
+
+ *p = q;
+ *allocated = newalloc;
+ return q;
+}
+
+void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
+ size_t prev;
+ uint8_t *q;
+
+ assert(p);
+ assert(allocated);
+
+ prev = *allocated;
+
+ q = greedy_realloc(p, allocated, need, size);
+ if (!q)
+ return NULL;
+
+ if (*allocated > prev)
+ memzero(q + prev * size, (*allocated - prev) * size);
+
+ return q;
+}
diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h
new file mode 100644
index 0000000000..12b602e185
--- /dev/null
+++ b/src/basic/alloc-util.h
@@ -0,0 +1,108 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <alloca.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "macro.h"
+
+#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n)))
+
+#define new0(t, n) ((t*) calloc((n), sizeof(t)))
+
+#define newa(t, n) ((t*) alloca(sizeof(t)*(n)))
+
+#define newa0(t, n) ((t*) alloca0(sizeof(t)*(n)))
+
+#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
+
+#define malloc0(n) (calloc(1, (n)))
+
+static inline void *mfree(void *memory) {
+ free(memory);
+ return NULL;
+}
+
+void* memdup(const void *p, size_t l) _alloc_(2);
+
+static inline void freep(void *p) {
+ free(*(void**) p);
+}
+
+#define _cleanup_free_ _cleanup_(freep)
+
+_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) {
+ if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
+ return NULL;
+
+ return malloc(a * b);
+}
+
+_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) {
+ if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
+ return NULL;
+
+ return realloc(p, a * b);
+}
+
+_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) {
+ if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
+ return NULL;
+
+ return memdup(p, a * b);
+}
+
+void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
+void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
+
+#define GREEDY_REALLOC(array, allocated, need) \
+ greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0]))
+
+#define GREEDY_REALLOC0(array, allocated, need) \
+ greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0]))
+
+#define alloca0(n) \
+ ({ \
+ char *_new_; \
+ size_t _len_ = n; \
+ _new_ = alloca(_len_); \
+ (void *) memset(_new_, 0, _len_); \
+ })
+
+/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */
+#define alloca_align(size, align) \
+ ({ \
+ void *_ptr_; \
+ size_t _mask_ = (align) - 1; \
+ _ptr_ = alloca((size) + _mask_); \
+ (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
+ })
+
+#define alloca0_align(size, align) \
+ ({ \
+ void *_new_; \
+ size_t _size_ = (size); \
+ _new_ = alloca_align(_size_, (align)); \
+ (void*)memset(_new_, 0, _size_); \
+ })
diff --git a/src/basic/audit.c b/src/basic/audit-util.c
index c9b762151a..4612297334 100644
--- a/src/basic/audit.c
+++ b/src/basic/audit-util.c
@@ -22,10 +22,12 @@
#include <errno.h>
#include <stdio.h>
-#include "audit.h"
+#include "alloc-util.h"
+#include "audit-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "macro.h"
+#include "parse-util.h"
#include "process-util.h"
#include "user-util.h"
#include "util.h"
diff --git a/src/basic/audit.h b/src/basic/audit-util.h
index 6de331c73e..6de331c73e 100644
--- a/src/basic/audit.h
+++ b/src/basic/audit-util.h
diff --git a/src/basic/bitmap.c b/src/basic/bitmap.c
index 2eabf3e1c1..1449e2ea85 100644
--- a/src/basic/bitmap.c
+++ b/src/basic/bitmap.c
@@ -19,9 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-
+#include "alloc-util.h"
#include "bitmap.h"
+#include "util.h"
struct Bitmap {
uint64_t *bitmaps;
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
index f799f8dcc2..4c90bc0c80 100644
--- a/src/basic/btrfs-util.c
+++ b/src/basic/btrfs-util.c
@@ -26,6 +26,7 @@
#include <linux/btrfs.h>
#endif
+#include "alloc-util.h"
#include "btrfs-ctree.h"
#include "btrfs-util.h"
#include "copy.h"
@@ -36,6 +37,7 @@
#include "path-util.h"
#include "selinux-util.h"
#include "smack-util.h"
+#include "stat-util.h"
#include "string-util.h"
#include "util.h"
@@ -60,13 +62,13 @@ static int validate_subvolume_name(const char *name) {
static int open_parent(const char *path, int flags) {
_cleanup_free_ char *parent = NULL;
- int r, fd;
+ int fd;
assert(path);
- r = path_get_parent(path, &parent);
- if (r < 0)
- return r;
+ parent = dirname_malloc(path);
+ if (!parent)
+ return -ENOMEM;
fd = open(parent, flags);
if (fd < 0)
diff --git a/src/basic/bus-label.c b/src/basic/bus-label.c
index ccc9f2bf8e..c1534657ac 100644
--- a/src/basic/bus-label.c
+++ b/src/basic/bus-label.c
@@ -21,10 +21,11 @@
#include <stdlib.h>
-#include "util.h"
-#include "macro.h"
-
+#include "alloc-util.h"
#include "bus-label.h"
+#include "hexdecoct.h"
+#include "macro.h"
+#include "util.h"
char *bus_label_escape(const char *s) {
char *r, *t;
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c
index 50328e4187..a6a906f453 100644
--- a/src/basic/calendarspec.c
+++ b/src/basic/calendarspec.c
@@ -22,8 +22,10 @@
#include <stdlib.h>
#include <string.h>
+#include "alloc-util.h"
#include "string-util.h"
#include "calendarspec.h"
+#include "fileio.h"
#define BITS_WEEKDAYS 127
diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c
index bd5bffbfa5..4d391510bc 100644
--- a/src/basic/cap-list.c
+++ b/src/basic/cap-list.c
@@ -21,9 +21,10 @@
#include <string.h>
-#include "util.h"
#include "cap-list.h"
#include "missing.h"
+#include "parse-util.h"
+#include "util.h"
static const struct capability_name* lookup_capability(register const char *str, register unsigned int len);
diff --git a/src/basic/capability.c b/src/basic/capability-util.c
index 6f25b5dee9..4479200306 100644
--- a/src/basic/capability.c
+++ b/src/basic/capability-util.c
@@ -26,10 +26,12 @@
#include <sys/prctl.h>
#include <unistd.h>
-#include "capability.h"
+#include "alloc-util.h"
+#include "capability-util.h"
#include "fileio.h"
#include "log.h"
#include "macro.h"
+#include "parse-util.h"
#include "util.h"
int have_effective_cap(int value) {
diff --git a/src/basic/capability.h b/src/basic/capability-util.h
index 4eb5c2a835..4eb5c2a835 100644
--- a/src/basic/capability.h
+++ b/src/basic/capability-util.h
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 4af991200c..f7fc2c2c97 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -29,18 +29,25 @@
#include <sys/types.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "cgroup-util.h"
+#include "dirent-util.h"
#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "login-util.h"
#include "macro.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "proc-cmdline.h"
#include "process-util.h"
#include "set.h"
#include "special.h"
+#include "stat-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "unit-name.h"
#include "user-util.h"
diff --git a/src/basic/chattr-util.c b/src/basic/chattr-util.c
new file mode 100644
index 0000000000..d49ca0537a
--- /dev/null
+++ b/src/basic/chattr-util.c
@@ -0,0 +1,107 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <linux/fs.h>
+
+#include "chattr-util.h"
+#include "fd-util.h"
+#include "util.h"
+
+int chattr_fd(int fd, unsigned value, unsigned mask) {
+ unsigned old_attr, new_attr;
+ struct stat st;
+
+ assert(fd >= 0);
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ /* Explicitly check whether this is a regular file or
+ * directory. If it is anything else (such as a device node or
+ * fifo), then the ioctl will not hit the file systems but
+ * possibly drivers, where the ioctl might have different
+ * effects. Notably, DRM is using the same ioctl() number. */
+
+ if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
+ return -ENOTTY;
+
+ if (mask == 0)
+ return 0;
+
+ if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0)
+ return -errno;
+
+ new_attr = (old_attr & ~mask) | (value & mask);
+ if (new_attr == old_attr)
+ return 0;
+
+ if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0)
+ return -errno;
+
+ return 1;
+}
+
+int chattr_path(const char *p, unsigned value, unsigned mask) {
+ _cleanup_close_ int fd = -1;
+
+ assert(p);
+
+ if (mask == 0)
+ return 0;
+
+ fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
+ if (fd < 0)
+ return -errno;
+
+ return chattr_fd(fd, value, mask);
+}
+
+int read_attr_fd(int fd, unsigned *ret) {
+ struct stat st;
+
+ assert(fd >= 0);
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
+ return -ENOTTY;
+
+ if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int read_attr_path(const char *p, unsigned *ret) {
+ _cleanup_close_ int fd = -1;
+
+ assert(p);
+ assert(ret);
+
+ fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
+ if (fd < 0)
+ return -errno;
+
+ return read_attr_fd(fd, ret);
+}
diff --git a/src/basic/chattr-util.h b/src/basic/chattr-util.h
new file mode 100644
index 0000000000..ba6b8eb5c1
--- /dev/null
+++ b/src/basic/chattr-util.h
@@ -0,0 +1,28 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+int chattr_fd(int fd, unsigned value, unsigned mask);
+int chattr_path(const char *p, unsigned value, unsigned mask);
+
+int read_attr_fd(int fd, unsigned *ret);
+int read_attr_path(const char *p, unsigned *ret);
diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c
index 3af3fe392c..be9972ffff 100644
--- a/src/basic/conf-files.c
+++ b/src/basic/conf-files.c
@@ -26,6 +26,7 @@
#include <string.h>
#include "conf-files.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "hashmap.h"
#include "log.h"
diff --git a/src/basic/copy.c b/src/basic/copy.c
index 9f274c4d51..a187ae08fe 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -22,13 +22,20 @@
#include <sys/sendfile.h>
#include <sys/xattr.h>
+#include "alloc-util.h"
#include "btrfs-util.h"
+#include "chattr-util.h"
#include "copy.h"
+#include "dirent-util.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "io-util.h"
#include "string-util.h"
#include "strv.h"
+#include "umask-util.h"
#include "util.h"
+#include "xattr-util.h"
#define COPY_BUFFER_SIZE (16*1024)
diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c
index 5e064d854f..4950c66767 100644
--- a/src/basic/cpu-set-util.c
+++ b/src/basic/cpu-set-util.c
@@ -20,9 +20,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
+#include "cpu-set-util.h"
#include "extract-word.h"
+#include "parse-util.h"
#include "util.h"
-#include "cpu-set-util.h"
cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
cpu_set_t *c;
@@ -70,14 +72,12 @@ int parse_cpu_set_and_warn(
for (;;) {
_cleanup_free_ char *word = NULL;
- unsigned cpu;
+ unsigned cpu, cpu_lower, cpu_upper;
int r;
- r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue);
- return r;
- }
+ r = extract_first_word(&rvalue, &word, WHITESPACE ",", EXTRACT_QUOTES);
+ if (r < 0)
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue);
if (r == 0)
break;
@@ -87,13 +87,17 @@ int parse_cpu_set_and_warn(
return log_oom();
}
- r = safe_atou(word, &cpu);
- if (r < 0 || cpu >= ncpus) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", rvalue);
- return -EINVAL;
- }
-
- CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
+ r = parse_range(word, &cpu_lower, &cpu_upper);
+ if (r < 0)
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", word);
+ if (cpu_lower >= ncpus || cpu_upper >= ncpus)
+ return log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU out of range '%s' ncpus is %u", word, ncpus);
+
+ if (cpu_lower > cpu_upper)
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u", word, cpu_lower, cpu_upper);
+ else
+ for (cpu = cpu_lower; cpu <= cpu_upper; cpu++)
+ CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
}
/* On success, sets *cpu_set and returns ncpus for the system. */
diff --git a/src/basic/device-nodes.h b/src/basic/device-nodes.h
index 04ba4897e5..7db81f3d52 100644
--- a/src/basic/device-nodes.h
+++ b/src/basic/device-nodes.h
@@ -21,5 +21,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <sys/types.h>
+
int encode_devnode_name(const char *str, char *str_enc, size_t len);
int whitelisted_char_for_devnode(char c, const char *additional);
diff --git a/src/basic/dirent-util.c b/src/basic/dirent-util.c
new file mode 100644
index 0000000000..c433d5844a
--- /dev/null
+++ b/src/basic/dirent-util.c
@@ -0,0 +1,81 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010-2012 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "dirent-util.h"
+#include "string-util.h"
+
+int dirent_ensure_type(DIR *d, struct dirent *de) {
+ struct stat st;
+
+ assert(d);
+ assert(de);
+
+ if (de->d_type != DT_UNKNOWN)
+ return 0;
+
+ if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
+ return -errno;
+
+ de->d_type =
+ S_ISREG(st.st_mode) ? DT_REG :
+ S_ISDIR(st.st_mode) ? DT_DIR :
+ S_ISLNK(st.st_mode) ? DT_LNK :
+ S_ISFIFO(st.st_mode) ? DT_FIFO :
+ S_ISSOCK(st.st_mode) ? DT_SOCK :
+ S_ISCHR(st.st_mode) ? DT_CHR :
+ S_ISBLK(st.st_mode) ? DT_BLK :
+ DT_UNKNOWN;
+
+ return 0;
+}
+
+bool dirent_is_file(const struct dirent *de) {
+ assert(de);
+
+ if (hidden_file(de->d_name))
+ return false;
+
+ if (de->d_type != DT_REG &&
+ de->d_type != DT_LNK &&
+ de->d_type != DT_UNKNOWN)
+ return false;
+
+ return true;
+}
+
+bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
+ assert(de);
+
+ if (de->d_type != DT_REG &&
+ de->d_type != DT_LNK &&
+ de->d_type != DT_UNKNOWN)
+ return false;
+
+ if (hidden_file_allow_backup(de->d_name))
+ return false;
+
+ return endswith(de->d_name, suffix);
+}
diff --git a/src/basic/dirent-util.h b/src/basic/dirent-util.h
new file mode 100644
index 0000000000..5866a755f4
--- /dev/null
+++ b/src/basic/dirent-util.h
@@ -0,0 +1,51 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <dirent.h>
+
+#include "path-util.h"
+
+int dirent_ensure_type(DIR *d, struct dirent *de);
+
+bool dirent_is_file(const struct dirent *de) _pure_;
+bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;
+
+#define FOREACH_DIRENT(de, d, on_error) \
+ for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \
+ if (!de) { \
+ if (errno > 0) { \
+ on_error; \
+ } \
+ break; \
+ } else if (hidden_file((de)->d_name)) \
+ continue; \
+ else
+
+#define FOREACH_DIRENT_ALL(de, d, on_error) \
+ for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \
+ if (!de) { \
+ if (errno > 0) { \
+ on_error; \
+ } \
+ break; \
+ } else
diff --git a/src/basic/env-util.c b/src/basic/env-util.c
index a392af737c..9ddac5d6a1 100644
--- a/src/basic/env-util.c
+++ b/src/basic/env-util.c
@@ -22,12 +22,14 @@
#include <limits.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "def.h"
+#include "env-util.h"
+#include "parse-util.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
#include "util.h"
-#include "env-util.h"
#define VALID_CHARS_ENV_NAME \
DIGITS LETTERS \
@@ -593,3 +595,13 @@ char **replace_env_argv(char **argv, char **env) {
ret[k] = NULL;
return ret;
}
+
+int getenv_bool(const char *p) {
+ const char *e;
+
+ e = getenv(p);
+ if (!e)
+ return -ENXIO;
+
+ return parse_boolean(e);
+}
diff --git a/src/basic/env-util.h b/src/basic/env-util.h
index 803aa61cad..6485dade18 100644
--- a/src/basic/env-util.h
+++ b/src/basic/env-util.h
@@ -47,3 +47,5 @@ char **strv_env_unset_many(char **l, ...) _sentinel_;
char *strv_env_get_n(char **l, const char *name, size_t k) _pure_;
char *strv_env_get(char **x, const char *n) _pure_;
+
+int getenv_bool(const char *p);
diff --git a/src/basic/escape.c b/src/basic/escape.c
index cf05ce10ef..add0d7795b 100644
--- a/src/basic/escape.c
+++ b/src/basic/escape.c
@@ -19,11 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
+#include "escape.h"
+#include "hexdecoct.h"
#include "utf8.h"
#include "util.h"
-#include "escape.h"
-
size_t cescape_char(char c, char *buf) {
char * buf_old = buf;
diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c
index f2b74802fa..c0f9394fad 100644
--- a/src/basic/extract-word.c
+++ b/src/basic/extract-word.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "escape.h"
#include "utf8.h"
#include "util.h"
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
index e54c104597..d1b1db3a4d 100644
--- a/src/basic/fd-util.c
+++ b/src/basic/fd-util.c
@@ -19,7 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "dirent-util.h"
#include "fd-util.h"
+#include "parse-util.h"
+#include "socket-util.h"
#include "util.h"
int close_nointr(int fd) {
@@ -319,3 +322,30 @@ void cmsg_close_all(struct msghdr *mh) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
}
+
+bool fdname_is_valid(const char *s) {
+ const char *p;
+
+ /* Validates a name for $LISTEN_FDNAMES. We basically allow
+ * everything ASCII that's not a control character. Also, as
+ * special exception the ":" character is not allowed, as we
+ * use that as field separator in $LISTEN_FDNAMES.
+ *
+ * Note that the empty string is explicitly allowed
+ * here. However, we limit the length of the names to 255
+ * characters. */
+
+ if (!s)
+ return false;
+
+ for (p = s; *p; p++) {
+ if (*p < ' ')
+ return false;
+ if (*p >= 127)
+ return false;
+ if (*p == ':')
+ return false;
+ }
+
+ return p - s < 256;
+}
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
index be00d881c3..1ca10f0383 100644
--- a/src/basic/fd-util.h
+++ b/src/basic/fd-util.h
@@ -67,3 +67,5 @@ int close_all_fds(const int except[], unsigned n_except);
int same_fd(int a, int b);
void cmsg_close_all(struct msghdr *mh);
+
+bool fdname_is_valid(const char *s);
diff --git a/src/basic/fdset.c b/src/basic/fdset.c
index 9669110828..42b0b2b98f 100644
--- a/src/basic/fdset.c
+++ b/src/basic/fdset.c
@@ -25,9 +25,11 @@
#include "sd-daemon.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "fdset.h"
#include "macro.h"
+#include "parse-util.h"
#include "set.h"
#include "util.h"
@@ -42,7 +44,7 @@ FDSet *fdset_new(void) {
return MAKE_FDSET(set_new(NULL));
}
-int fdset_new_array(FDSet **ret, int *fds, unsigned n_fds) {
+int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds) {
unsigned i;
FDSet *s;
int r;
diff --git a/src/basic/fdset.h b/src/basic/fdset.h
index 340438d7c4..70d8acbcff 100644
--- a/src/basic/fdset.h
+++ b/src/basic/fdset.h
@@ -35,7 +35,7 @@ int fdset_consume(FDSet *s, int fd);
bool fdset_contains(FDSet *s, int fd);
int fdset_remove(FDSet *s, int fd);
-int fdset_new_array(FDSet **ret, int *fds, unsigned n_fds);
+int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds);
int fdset_new_fill(FDSet **ret);
int fdset_new_listen_fds(FDSet **ret, bool unset);
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 5d33309ab2..619dafb517 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -21,12 +21,18 @@
#include <unistd.h>
+#include "alloc-util.h"
#include "ctype.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
+#include "hexdecoct.h"
+#include "path-util.h"
+#include "random-util.h"
#include "string-util.h"
#include "strv.h"
+#include "umask-util.h"
#include "utf8.h"
#include "util.h"
@@ -54,7 +60,7 @@ static int write_string_file_atomic(const char *fn, const char *line, bool enfor
if (r < 0)
return r;
- fchmod_umask(fileno(f), 0644);
+ (void) fchmod_umask(fileno(f), 0644);
r = write_string_stream(f, line, enforce_newline);
if (r >= 0) {
@@ -63,7 +69,7 @@ static int write_string_file_atomic(const char *fn, const char *line, bool enfor
}
if (r < 0)
- unlink(p);
+ (void) unlink(p);
return r;
}
@@ -848,3 +854,298 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin
*field = f;
return 0;
}
+
+DIR *xopendirat(int fd, const char *name, int flags) {
+ int nfd;
+ DIR *d;
+
+ assert(!(flags & O_CREAT));
+
+ nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
+ if (nfd < 0)
+ return NULL;
+
+ d = fdopendir(nfd);
+ if (!d) {
+ safe_close(nfd);
+ return NULL;
+ }
+
+ return d;
+}
+
+static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
+ char **i;
+
+ assert(path);
+ assert(mode);
+ assert(_f);
+
+ if (!path_strv_resolve_uniq(search, root))
+ return -ENOMEM;
+
+ STRV_FOREACH(i, search) {
+ _cleanup_free_ char *p = NULL;
+ FILE *f;
+
+ if (root)
+ p = strjoin(root, *i, "/", path, NULL);
+ else
+ p = strjoin(*i, "/", path, NULL);
+ if (!p)
+ return -ENOMEM;
+
+ f = fopen(p, mode);
+ if (f) {
+ *_f = f;
+ return 0;
+ }
+
+ if (errno != ENOENT)
+ return -errno;
+ }
+
+ return -ENOENT;
+}
+
+int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
+ _cleanup_strv_free_ char **copy = NULL;
+
+ assert(path);
+ assert(mode);
+ assert(_f);
+
+ if (path_is_absolute(path)) {
+ FILE *f;
+
+ f = fopen(path, mode);
+ if (f) {
+ *_f = f;
+ return 0;
+ }
+
+ return -errno;
+ }
+
+ copy = strv_copy((char**) search);
+ if (!copy)
+ return -ENOMEM;
+
+ return search_and_fopen_internal(path, mode, root, copy, _f);
+}
+
+int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
+ _cleanup_strv_free_ char **s = NULL;
+
+ if (path_is_absolute(path)) {
+ FILE *f;
+
+ f = fopen(path, mode);
+ if (f) {
+ *_f = f;
+ return 0;
+ }
+
+ return -errno;
+ }
+
+ s = strv_split_nulstr(search);
+ if (!s)
+ return -ENOMEM;
+
+ return search_and_fopen_internal(path, mode, root, s, _f);
+}
+
+int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
+ FILE *f;
+ char *t;
+ int r, fd;
+
+ assert(path);
+ assert(_f);
+ assert(_temp_path);
+
+ r = tempfn_xxxxxx(path, NULL, &t);
+ if (r < 0)
+ return r;
+
+ fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
+ if (fd < 0) {
+ free(t);
+ return -errno;
+ }
+
+ f = fdopen(fd, "we");
+ if (!f) {
+ unlink_noerrno(t);
+ free(t);
+ safe_close(fd);
+ return -errno;
+ }
+
+ *_f = f;
+ *_temp_path = t;
+
+ return 0;
+}
+
+int fflush_and_check(FILE *f) {
+ assert(f);
+
+ errno = 0;
+ fflush(f);
+
+ if (ferror(f))
+ return errno ? -errno : -EIO;
+
+ return 0;
+}
+
+/* This is much like like mkostemp() but is subject to umask(). */
+int mkostemp_safe(char *pattern, int flags) {
+ _cleanup_umask_ mode_t u;
+ int fd;
+
+ assert(pattern);
+
+ u = umask(077);
+
+ fd = mkostemp(pattern, flags);
+ if (fd < 0)
+ return -errno;
+
+ return fd;
+}
+
+int open_tmpfile(const char *path, int flags) {
+ char *p;
+ int fd;
+
+ assert(path);
+
+#ifdef O_TMPFILE
+ /* Try O_TMPFILE first, if it is supported */
+ fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
+ if (fd >= 0)
+ return fd;
+#endif
+
+ /* Fall back to unguessable name + unlinking */
+ p = strjoina(path, "/systemd-tmp-XXXXXX");
+
+ fd = mkostemp_safe(p, flags);
+ if (fd < 0)
+ return fd;
+
+ unlink(p);
+ return fd;
+}
+
+int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
+ const char *fn;
+ char *t;
+
+ assert(p);
+ assert(ret);
+
+ /*
+ * Turns this:
+ * /foo/bar/waldo
+ *
+ * Into this:
+ * /foo/bar/.#<extra>waldoXXXXXX
+ */
+
+ fn = basename(p);
+ if (!filename_is_valid(fn))
+ return -EINVAL;
+
+ if (extra == NULL)
+ extra = "";
+
+ t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1);
+ if (!t)
+ return -ENOMEM;
+
+ strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX");
+
+ *ret = path_kill_slashes(t);
+ return 0;
+}
+
+int tempfn_random(const char *p, const char *extra, char **ret) {
+ const char *fn;
+ char *t, *x;
+ uint64_t u;
+ unsigned i;
+
+ assert(p);
+ assert(ret);
+
+ /*
+ * Turns this:
+ * /foo/bar/waldo
+ *
+ * Into this:
+ * /foo/bar/.#<extra>waldobaa2a261115984a9
+ */
+
+ fn = basename(p);
+ if (!filename_is_valid(fn))
+ return -EINVAL;
+
+ if (!extra)
+ extra = "";
+
+ t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1);
+ if (!t)
+ return -ENOMEM;
+
+ x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn);
+
+ u = random_u64();
+ for (i = 0; i < 16; i++) {
+ *(x++) = hexchar(u & 0xF);
+ u >>= 4;
+ }
+
+ *x = 0;
+
+ *ret = path_kill_slashes(t);
+ return 0;
+}
+
+int tempfn_random_child(const char *p, const char *extra, char **ret) {
+ char *t, *x;
+ uint64_t u;
+ unsigned i;
+
+ assert(p);
+ assert(ret);
+
+ /* Turns this:
+ * /foo/bar/waldo
+ * Into this:
+ * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
+ */
+
+ if (!extra)
+ extra = "";
+
+ t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1);
+ if (!t)
+ return -ENOMEM;
+
+ x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
+
+ u = random_u64();
+ for (i = 0; i < 16; i++) {
+ *(x++) = hexchar(u & 0xF);
+ u >>= 4;
+ }
+
+ *x = 0;
+
+ *ret = path_kill_slashes(t);
+ return 0;
+}
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index 4998d4d042..fa7f192331 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -20,8 +20,12 @@
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+
+#include <dirent.h>
+#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
+#include <sys/types.h>
#include "macro.h"
@@ -49,3 +53,27 @@ int write_env_file(const char *fname, char **l);
int executable_is_script(const char *path, char **interpreter);
int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field);
+
+DIR *xopendirat(int dirfd, const char *name, int flags);
+
+int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
+int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
+
+#define FOREACH_LINE(line, f, on_error) \
+ for (;;) \
+ if (!fgets(line, sizeof(line), f)) { \
+ if (ferror(f)) { \
+ on_error; \
+ } \
+ break; \
+ } else
+
+int fflush_and_check(FILE *f);
+
+int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
+int mkostemp_safe(char *pattern, int flags);
+int open_tmpfile(const char *path, int flags);
+
+int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
+int tempfn_random(const char *p, const char *extra, char **ret);
+int tempfn_random_child(const char *p, const char *extra, char **ret);
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
new file mode 100644
index 0000000000..7aee404bfc
--- /dev/null
+++ b/src/basic/fs-util.c
@@ -0,0 +1,480 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "dirent-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "mkdir.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "user-util.h"
+#include "util.h"
+
+int unlink_noerrno(const char *path) {
+ PROTECT_ERRNO;
+ int r;
+
+ r = unlink(path);
+ if (r < 0)
+ return -errno;
+
+ return 0;
+}
+
+int rmdir_parents(const char *path, const char *stop) {
+ size_t l;
+ int r = 0;
+
+ assert(path);
+ assert(stop);
+
+ l = strlen(path);
+
+ /* Skip trailing slashes */
+ while (l > 0 && path[l-1] == '/')
+ l--;
+
+ while (l > 0) {
+ char *t;
+
+ /* Skip last component */
+ while (l > 0 && path[l-1] != '/')
+ l--;
+
+ /* Skip trailing slashes */
+ while (l > 0 && path[l-1] == '/')
+ l--;
+
+ if (l <= 0)
+ break;
+
+ t = strndup(path, l);
+ if (!t)
+ return -ENOMEM;
+
+ if (path_startswith(stop, t)) {
+ free(t);
+ return 0;
+ }
+
+ r = rmdir(t);
+ free(t);
+
+ if (r < 0)
+ if (errno != ENOENT)
+ return -errno;
+ }
+
+ return 0;
+}
+
+
+int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
+ struct stat buf;
+ int ret;
+
+ ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
+ if (ret >= 0)
+ return 0;
+
+ /* renameat2() exists since Linux 3.15, btrfs added support for it later.
+ * If it is not implemented, fallback to another method. */
+ if (!IN_SET(errno, EINVAL, ENOSYS))
+ return -errno;
+
+ /* The link()/unlink() fallback does not work on directories. But
+ * renameat() without RENAME_NOREPLACE gives the same semantics on
+ * directories, except when newpath is an *empty* directory. This is
+ * good enough. */
+ ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
+ if (ret >= 0 && S_ISDIR(buf.st_mode)) {
+ ret = renameat(olddirfd, oldpath, newdirfd, newpath);
+ return ret >= 0 ? 0 : -errno;
+ }
+
+ /* If it is not a directory, use the link()/unlink() fallback. */
+ ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
+ if (ret < 0)
+ return -errno;
+
+ ret = unlinkat(olddirfd, oldpath, 0);
+ if (ret < 0) {
+ /* backup errno before the following unlinkat() alters it */
+ ret = errno;
+ (void) unlinkat(newdirfd, newpath, 0);
+ errno = ret;
+ return -errno;
+ }
+
+ return 0;
+}
+
+int readlinkat_malloc(int fd, const char *p, char **ret) {
+ size_t l = 100;
+ int r;
+
+ assert(p);
+ assert(ret);
+
+ for (;;) {
+ char *c;
+ ssize_t n;
+
+ c = new(char, l);
+ if (!c)
+ return -ENOMEM;
+
+ n = readlinkat(fd, p, c, l-1);
+ if (n < 0) {
+ r = -errno;
+ free(c);
+ return r;
+ }
+
+ if ((size_t) n < l-1) {
+ c[n] = 0;
+ *ret = c;
+ return 0;
+ }
+
+ free(c);
+ l *= 2;
+ }
+}
+
+int readlink_malloc(const char *p, char **ret) {
+ return readlinkat_malloc(AT_FDCWD, p, ret);
+}
+
+int readlink_value(const char *p, char **ret) {
+ _cleanup_free_ char *link = NULL;
+ char *value;
+ int r;
+
+ r = readlink_malloc(p, &link);
+ if (r < 0)
+ return r;
+
+ value = basename(link);
+ if (!value)
+ return -ENOENT;
+
+ value = strdup(value);
+ if (!value)
+ return -ENOMEM;
+
+ *ret = value;
+
+ return 0;
+}
+
+int readlink_and_make_absolute(const char *p, char **r) {
+ _cleanup_free_ char *target = NULL;
+ char *k;
+ int j;
+
+ assert(p);
+ assert(r);
+
+ j = readlink_malloc(p, &target);
+ if (j < 0)
+ return j;
+
+ k = file_in_same_dir(p, target);
+ if (!k)
+ return -ENOMEM;
+
+ *r = k;
+ return 0;
+}
+
+int readlink_and_canonicalize(const char *p, char **r) {
+ char *t, *s;
+ int j;
+
+ assert(p);
+ assert(r);
+
+ j = readlink_and_make_absolute(p, &t);
+ if (j < 0)
+ return j;
+
+ s = canonicalize_file_name(t);
+ if (s) {
+ free(t);
+ *r = s;
+ } else
+ *r = t;
+
+ path_kill_slashes(*r);
+
+ return 0;
+}
+
+int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
+ assert(path);
+
+ /* Under the assumption that we are running privileged we
+ * first change the access mode and only then hand out
+ * ownership to avoid a window where access is too open. */
+
+ if (mode != MODE_INVALID)
+ if (chmod(path, mode) < 0)
+ return -errno;
+
+ if (uid != UID_INVALID || gid != GID_INVALID)
+ if (chown(path, uid, gid) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
+ assert(fd >= 0);
+
+ /* Under the assumption that we are running privileged we
+ * first change the access mode and only then hand out
+ * ownership to avoid a window where access is too open. */
+
+ if (mode != MODE_INVALID)
+ if (fchmod(fd, mode) < 0)
+ return -errno;
+
+ if (uid != UID_INVALID || gid != GID_INVALID)
+ if (fchown(fd, uid, gid) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int fchmod_umask(int fd, mode_t m) {
+ mode_t u;
+ int r;
+
+ u = umask(0777);
+ r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
+ umask(u);
+
+ return r;
+}
+
+int fd_warn_permissions(const char *path, int fd) {
+ struct stat st;
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ if (st.st_mode & 0111)
+ log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
+
+ if (st.st_mode & 0002)
+ log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
+
+ if (getpid() == 1 && (st.st_mode & 0044) != 0044)
+ log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path);
+
+ return 0;
+}
+
+int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
+ _cleanup_close_ int fd;
+ int r;
+
+ assert(path);
+
+ if (parents)
+ mkdir_parents(path, 0755);
+
+ fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
+ if (fd < 0)
+ return -errno;
+
+ if (mode > 0) {
+ r = fchmod(fd, mode);
+ if (r < 0)
+ return -errno;
+ }
+
+ if (uid != UID_INVALID || gid != GID_INVALID) {
+ r = fchown(fd, uid, gid);
+ if (r < 0)
+ return -errno;
+ }
+
+ if (stamp != USEC_INFINITY) {
+ struct timespec ts[2];
+
+ timespec_store(&ts[0], stamp);
+ ts[1] = ts[0];
+ r = futimens(fd, ts);
+ } else
+ r = futimens(fd, NULL);
+ if (r < 0)
+ return -errno;
+
+ return 0;
+}
+
+int touch(const char *path) {
+ return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
+}
+
+int symlink_idempotent(const char *from, const char *to) {
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ assert(from);
+ assert(to);
+
+ if (symlink(from, to) < 0) {
+ if (errno != EEXIST)
+ return -errno;
+
+ r = readlink_malloc(to, &p);
+ if (r < 0)
+ return r;
+
+ if (!streq(p, from))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int symlink_atomic(const char *from, const char *to) {
+ _cleanup_free_ char *t = NULL;
+ int r;
+
+ assert(from);
+ assert(to);
+
+ r = tempfn_random(to, NULL, &t);
+ if (r < 0)
+ return r;
+
+ if (symlink(from, t) < 0)
+ return -errno;
+
+ if (rename(t, to) < 0) {
+ unlink_noerrno(t);
+ return -errno;
+ }
+
+ return 0;
+}
+
+int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
+ _cleanup_free_ char *t = NULL;
+ int r;
+
+ assert(path);
+
+ r = tempfn_random(path, NULL, &t);
+ if (r < 0)
+ return r;
+
+ if (mknod(t, mode, dev) < 0)
+ return -errno;
+
+ if (rename(t, path) < 0) {
+ unlink_noerrno(t);
+ return -errno;
+ }
+
+ return 0;
+}
+
+int mkfifo_atomic(const char *path, mode_t mode) {
+ _cleanup_free_ char *t = NULL;
+ int r;
+
+ assert(path);
+
+ r = tempfn_random(path, NULL, &t);
+ if (r < 0)
+ return r;
+
+ if (mkfifo(t, mode) < 0)
+ return -errno;
+
+ if (rename(t, path) < 0) {
+ unlink_noerrno(t);
+ return -errno;
+ }
+
+ return 0;
+}
+
+int get_files_in_directory(const char *path, char ***list) {
+ _cleanup_closedir_ DIR *d = NULL;
+ size_t bufsize = 0, n = 0;
+ _cleanup_strv_free_ char **l = NULL;
+
+ assert(path);
+
+ /* Returns all files in a directory in *list, and the number
+ * of files as return value. If list is NULL returns only the
+ * number. */
+
+ d = opendir(path);
+ if (!d)
+ return -errno;
+
+ for (;;) {
+ struct dirent *de;
+
+ errno = 0;
+ de = readdir(d);
+ if (!de && errno != 0)
+ return -errno;
+ if (!de)
+ break;
+
+ dirent_ensure_type(d, de);
+
+ if (!dirent_is_file(de))
+ continue;
+
+ if (list) {
+ /* one extra slot is needed for the terminating NULL */
+ if (!GREEDY_REALLOC(l, bufsize, n + 2))
+ return -ENOMEM;
+
+ l[n] = strdup(de->d_name);
+ if (!l[n])
+ return -ENOMEM;
+
+ l[++n] = NULL;
+ } else
+ n++;
+ }
+
+ if (list) {
+ *list = l;
+ l = NULL; /* avoid freeing */
+ }
+
+ return n;
+}
diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
new file mode 100644
index 0000000000..b94873e65b
--- /dev/null
+++ b/src/basic/fs-util.h
@@ -0,0 +1,74 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <fcntl.h>
+#include <sys/inotify.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "time-util.h"
+
+int unlink_noerrno(const char *path);
+
+int rmdir_parents(const char *path, const char *stop);
+
+int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
+
+int readlinkat_malloc(int fd, const char *p, char **ret);
+int readlink_malloc(const char *p, char **r);
+int readlink_value(const char *p, char **ret);
+int readlink_and_make_absolute(const char *p, char **r);
+int readlink_and_canonicalize(const char *p, char **r);
+
+int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
+int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
+
+int fchmod_umask(int fd, mode_t mode);
+
+int fd_warn_permissions(const char *path, int fd);
+
+#define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW)
+
+int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode);
+int touch(const char *path);
+
+int symlink_idempotent(const char *from, const char *to);
+
+int symlink_atomic(const char *from, const char *to);
+int mknod_atomic(const char *path, mode_t mode, dev_t dev);
+int mkfifo_atomic(const char *path, mode_t mode);
+
+int get_files_in_directory(const char *path, char ***list);
+
+#define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
+
+#define FOREACH_INOTIFY_EVENT(e, buffer, sz) \
+ for ((e) = &buffer.ev; \
+ (uint8_t*) (e) < (uint8_t*) (buffer.raw) + (sz); \
+ (e) = (struct inotify_event*) ((uint8_t*) (e) + sizeof(struct inotify_event) + (e)->len))
+
+union inotify_event_buffer {
+ struct inotify_event ev;
+ uint8_t raw[INOTIFY_EVENT_MAX];
+};
diff --git a/src/basic/glob-util.c b/src/basic/glob-util.c
new file mode 100644
index 0000000000..112c6392e5
--- /dev/null
+++ b/src/basic/glob-util.c
@@ -0,0 +1,71 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <glob.h>
+
+#include "glob-util.h"
+#include "strv.h"
+#include "util.h"
+
+int glob_exists(const char *path) {
+ _cleanup_globfree_ glob_t g = {};
+ int k;
+
+ assert(path);
+
+ errno = 0;
+ k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
+
+ if (k == GLOB_NOMATCH)
+ return 0;
+ if (k == GLOB_NOSPACE)
+ return -ENOMEM;
+ if (k != 0)
+ return errno ? -errno : -EIO;
+
+ return !strv_isempty(g.gl_pathv);
+}
+
+int glob_extend(char ***strv, const char *path) {
+ _cleanup_globfree_ glob_t g = {};
+ int k;
+ char **p;
+
+ errno = 0;
+ k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
+
+ if (k == GLOB_NOMATCH)
+ return -ENOENT;
+ if (k == GLOB_NOSPACE)
+ return -ENOMEM;
+ if (k != 0)
+ return errno ? -errno : -EIO;
+ if (strv_isempty(g.gl_pathv))
+ return -ENOENT;
+
+ STRV_FOREACH(p, g.gl_pathv) {
+ k = strv_extend(strv, *p);
+ if (k < 0)
+ return k;
+ }
+
+ return 0;
+}
diff --git a/src/basic/glob-util.h b/src/basic/glob-util.h
new file mode 100644
index 0000000000..8817df14b4
--- /dev/null
+++ b/src/basic/glob-util.h
@@ -0,0 +1,37 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <string.h>
+
+#include "macro.h"
+#include "util.h"
+
+int glob_exists(const char *path);
+int glob_extend(char ***strv, const char *path);
+
+#define _cleanup_globfree_ _cleanup_(globfree)
+
+_pure_ static inline bool string_is_glob(const char *p) {
+ /* Check if a string contains any glob patterns. */
+ return !!strpbrk(p, GLOB_CHARS);
+}
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index 20e7e51d9e..4109a08c6c 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -20,18 +20,20 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
+#include <stdlib.h>
-#include "util.h"
+#include "alloc-util.h"
#include "hashmap.h"
-#include "set.h"
#include "macro.h"
-#include "siphash24.h"
-#include "strv.h"
#include "mempool.h"
+#include "process-util.h"
#include "random-util.h"
+#include "set.h"
+#include "siphash24.h"
+#include "strv.h"
+#include "util.h"
#ifdef ENABLE_DEBUG_HASHMAP
#include "list.h"
diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c
new file mode 100644
index 0000000000..4eb566b15a
--- /dev/null
+++ b/src/basic/hexdecoct.c
@@ -0,0 +1,698 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <ctype.h>
+#include <inttypes.h>
+
+#include "alloc-util.h"
+#include "hexdecoct.h"
+#include "util.h"
+
+char octchar(int x) {
+ return '0' + (x & 7);
+}
+
+int unoctchar(char c) {
+
+ if (c >= '0' && c <= '7')
+ return c - '0';
+
+ return -EINVAL;
+}
+
+char decchar(int x) {
+ return '0' + (x % 10);
+}
+
+int undecchar(char c) {
+
+ if (c >= '0' && c <= '9')
+ return c - '0';
+
+ return -EINVAL;
+}
+
+char hexchar(int x) {
+ static const char table[16] = "0123456789abcdef";
+
+ return table[x & 15];
+}
+
+int unhexchar(char c) {
+
+ if (c >= '0' && c <= '9')
+ return c - '0';
+
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+
+ return -EINVAL;
+}
+
+char *hexmem(const void *p, size_t l) {
+ char *r, *z;
+ const uint8_t *x;
+
+ z = r = malloc(l * 2 + 1);
+ if (!r)
+ return NULL;
+
+ for (x = p; x < (const uint8_t*) p + l; x++) {
+ *(z++) = hexchar(*x >> 4);
+ *(z++) = hexchar(*x & 15);
+ }
+
+ *z = 0;
+ return r;
+}
+
+int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
+ _cleanup_free_ uint8_t *r = NULL;
+ uint8_t *z;
+ const char *x;
+
+ assert(mem);
+ assert(len);
+ assert(p);
+
+ z = r = malloc((l + 1) / 2 + 1);
+ if (!r)
+ return -ENOMEM;
+
+ for (x = p; x < p + l; x += 2) {
+ int a, b;
+
+ a = unhexchar(x[0]);
+ if (a < 0)
+ return a;
+ else if (x+1 < p + l) {
+ b = unhexchar(x[1]);
+ if (b < 0)
+ return b;
+ } else
+ b = 0;
+
+ *(z++) = (uint8_t) a << 4 | (uint8_t) b;
+ }
+
+ *z = 0;
+
+ *mem = r;
+ r = NULL;
+ *len = (l + 1) / 2;
+
+ return 0;
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-6
+ * Notice that base32hex differs from base32 in the alphabet it uses.
+ * The distinction is that the base32hex representation preserves the
+ * order of the underlying data when compared as bytestrings, this is
+ * useful when representing NSEC3 hashes, as one can then verify the
+ * order of hashes directly from their representation. */
+char base32hexchar(int x) {
+ static const char table[32] = "0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUV";
+
+ return table[x & 31];
+}
+
+int unbase32hexchar(char c) {
+ unsigned offset;
+
+ if (c >= '0' && c <= '9')
+ return c - '0';
+
+ offset = '9' - '0' + 1;
+
+ if (c >= 'A' && c <= 'V')
+ return c - 'A' + offset;
+
+ return -EINVAL;
+}
+
+char *base32hexmem(const void *p, size_t l, bool padding) {
+ char *r, *z;
+ const uint8_t *x;
+ size_t len;
+
+ if (padding)
+ /* five input bytes makes eight output bytes, padding is added so we must round up */
+ len = 8 * (l + 4) / 5;
+ else {
+ /* same, but round down as there is no padding */
+ len = 8 * l / 5;
+
+ switch (l % 5) {
+ case 4:
+ len += 7;
+ break;
+ case 3:
+ len += 5;
+ break;
+ case 2:
+ len += 4;
+ break;
+ case 1:
+ len += 2;
+ break;
+ }
+ }
+
+ z = r = malloc(len + 1);
+ if (!r)
+ return NULL;
+
+ for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
+ /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
+ x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
+ *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
+ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
+ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
+ *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
+ *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
+ *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
+ *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */
+ *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */
+ }
+
+ switch (l % 5) {
+ case 4:
+ *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
+ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
+ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
+ *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
+ *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
+ *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
+ *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */
+ if (padding)
+ *(z++) = '=';
+
+ break;
+
+ case 3:
+ *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
+ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
+ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
+ *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
+ *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */
+ if (padding) {
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ }
+
+ break;
+
+ case 2:
+ *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
+ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
+ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
+ *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */
+ if (padding) {
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ }
+
+ break;
+
+ case 1:
+ *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
+ *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
+ if (padding) {
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ *(z++) = '=';
+ }
+
+ break;
+ }
+
+ *z = 0;
+ return r;
+}
+
+int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
+ _cleanup_free_ uint8_t *r = NULL;
+ int a, b, c, d, e, f, g, h;
+ uint8_t *z;
+ const char *x;
+ size_t len;
+ unsigned pad = 0;
+
+ assert(p);
+
+ /* padding ensures any base32hex input has input divisible by 8 */
+ if (padding && l % 8 != 0)
+ return -EINVAL;
+
+ if (padding) {
+ /* strip the padding */
+ while (l > 0 && p[l - 1] == '=' && pad < 7) {
+ pad ++;
+ l --;
+ }
+ }
+
+ /* a group of eight input bytes needs five output bytes, in case of
+ padding we need to add some extra bytes */
+ len = (l / 8) * 5;
+
+ switch (l % 8) {
+ case 7:
+ len += 4;
+ break;
+ case 5:
+ len += 3;
+ break;
+ case 4:
+ len += 2;
+ break;
+ case 2:
+ len += 1;
+ break;
+ case 0:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ z = r = malloc(len + 1);
+ if (!r)
+ return -ENOMEM;
+
+ for (x = p; x < p + (l / 8) * 8; x += 8) {
+ /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
+ e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
+ a = unbase32hexchar(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase32hexchar(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ c = unbase32hexchar(x[2]);
+ if (c < 0)
+ return -EINVAL;
+
+ d = unbase32hexchar(x[3]);
+ if (d < 0)
+ return -EINVAL;
+
+ e = unbase32hexchar(x[4]);
+ if (e < 0)
+ return -EINVAL;
+
+ f = unbase32hexchar(x[5]);
+ if (f < 0)
+ return -EINVAL;
+
+ g = unbase32hexchar(x[6]);
+ if (g < 0)
+ return -EINVAL;
+
+ h = unbase32hexchar(x[7]);
+ if (h < 0)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
+ *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
+ *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
+ *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
+ *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */
+ }
+
+ switch (l % 8) {
+ case 7:
+ a = unbase32hexchar(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase32hexchar(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ c = unbase32hexchar(x[2]);
+ if (c < 0)
+ return -EINVAL;
+
+ d = unbase32hexchar(x[3]);
+ if (d < 0)
+ return -EINVAL;
+
+ e = unbase32hexchar(x[4]);
+ if (e < 0)
+ return -EINVAL;
+
+ f = unbase32hexchar(x[5]);
+ if (f < 0)
+ return -EINVAL;
+
+ g = unbase32hexchar(x[6]);
+ if (g < 0)
+ return -EINVAL;
+
+ /* g == 000VV000 */
+ if (g & 7)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
+ *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
+ *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
+ *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
+
+ break;
+ case 5:
+ a = unbase32hexchar(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase32hexchar(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ c = unbase32hexchar(x[2]);
+ if (c < 0)
+ return -EINVAL;
+
+ d = unbase32hexchar(x[3]);
+ if (d < 0)
+ return -EINVAL;
+
+ e = unbase32hexchar(x[4]);
+ if (e < 0)
+ return -EINVAL;
+
+ /* e == 000SSSS0 */
+ if (e & 1)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
+ *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
+ *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
+
+ break;
+ case 4:
+ a = unbase32hexchar(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase32hexchar(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ c = unbase32hexchar(x[2]);
+ if (c < 0)
+ return -EINVAL;
+
+ d = unbase32hexchar(x[3]);
+ if (d < 0)
+ return -EINVAL;
+
+ /* d == 000W0000 */
+ if (d & 15)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
+ *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
+
+ break;
+ case 2:
+ a = unbase32hexchar(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase32hexchar(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ /* b == 000YYY00 */
+ if (b & 3)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
+
+ break;
+ case 0:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *z = 0;
+
+ *mem = r;
+ r = NULL;
+ *_len = len;
+
+ return 0;
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-4 */
+char base64char(int x) {
+ static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+ return table[x & 63];
+}
+
+int unbase64char(char c) {
+ unsigned offset;
+
+ if (c >= 'A' && c <= 'Z')
+ return c - 'A';
+
+ offset = 'Z' - 'A' + 1;
+
+ if (c >= 'a' && c <= 'z')
+ return c - 'a' + offset;
+
+ offset += 'z' - 'a' + 1;
+
+ if (c >= '0' && c <= '9')
+ return c - '0' + offset;
+
+ offset += '9' - '0' + 1;
+
+ if (c == '+')
+ return offset;
+
+ offset ++;
+
+ if (c == '/')
+ return offset;
+
+ return -EINVAL;
+}
+
+char *base64mem(const void *p, size_t l) {
+ char *r, *z;
+ const uint8_t *x;
+
+ /* three input bytes makes four output bytes, padding is added so we must round up */
+ z = r = malloc(4 * (l + 2) / 3 + 1);
+ if (!r)
+ return NULL;
+
+ for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
+ /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
+ *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
+ *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
+ *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
+ *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
+ }
+
+ switch (l % 3) {
+ case 2:
+ *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
+ *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
+ *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
+ *(z++) = '=';
+
+ break;
+ case 1:
+ *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
+ *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
+ *(z++) = '=';
+ *(z++) = '=';
+
+ break;
+ }
+
+ *z = 0;
+ return r;
+}
+
+int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
+ _cleanup_free_ uint8_t *r = NULL;
+ int a, b, c, d;
+ uint8_t *z;
+ const char *x;
+ size_t len;
+
+ assert(p);
+
+ /* padding ensures any base63 input has input divisible by 4 */
+ if (l % 4 != 0)
+ return -EINVAL;
+
+ /* strip the padding */
+ if (l > 0 && p[l - 1] == '=')
+ l --;
+ if (l > 0 && p[l - 1] == '=')
+ l --;
+
+ /* a group of four input bytes needs three output bytes, in case of
+ padding we need to add two or three extra bytes */
+ len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0);
+
+ z = r = malloc(len + 1);
+ if (!r)
+ return -ENOMEM;
+
+ for (x = p; x < p + (l / 4) * 4; x += 4) {
+ /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
+ a = unbase64char(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase64char(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ c = unbase64char(x[2]);
+ if (c < 0)
+ return -EINVAL;
+
+ d = unbase64char(x[3]);
+ if (d < 0)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
+ *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
+ *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
+ }
+
+ switch (l % 4) {
+ case 3:
+ a = unbase64char(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase64char(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ c = unbase64char(x[2]);
+ if (c < 0)
+ return -EINVAL;
+
+ /* c == 00ZZZZ00 */
+ if (c & 3)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
+ *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
+
+ break;
+ case 2:
+ a = unbase64char(x[0]);
+ if (a < 0)
+ return -EINVAL;
+
+ b = unbase64char(x[1]);
+ if (b < 0)
+ return -EINVAL;
+
+ /* b == 00YY0000 */
+ if (b & 15)
+ return -EINVAL;
+
+ *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
+
+ break;
+ case 0:
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *z = 0;
+
+ *mem = r;
+ r = NULL;
+ *_len = len;
+
+ return 0;
+}
+
+void hexdump(FILE *f, const void *p, size_t s) {
+ const uint8_t *b = p;
+ unsigned n = 0;
+
+ assert(s == 0 || b);
+
+ while (s > 0) {
+ size_t i;
+
+ fprintf(f, "%04x ", n);
+
+ for (i = 0; i < 16; i++) {
+
+ if (i >= s)
+ fputs(" ", f);
+ else
+ fprintf(f, "%02x ", b[i]);
+
+ if (i == 7)
+ fputc(' ', f);
+ }
+
+ fputc(' ', f);
+
+ for (i = 0; i < 16; i++) {
+
+ if (i >= s)
+ fputc(' ', f);
+ else
+ fputc(isprint(b[i]) ? (char) b[i] : '.', f);
+ }
+
+ fputc('\n', f);
+
+ if (s < 16)
+ break;
+
+ n += 16;
+ b += 16;
+ s -= 16;
+ }
+}
diff --git a/src/basic/hexdecoct.h b/src/basic/hexdecoct.h
new file mode 100644
index 0000000000..4aeb4c3bdc
--- /dev/null
+++ b/src/basic/hexdecoct.h
@@ -0,0 +1,54 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "macro.h"
+
+char octchar(int x) _const_;
+int unoctchar(char c) _const_;
+
+char decchar(int x) _const_;
+int undecchar(char c) _const_;
+
+char hexchar(int x) _const_;
+int unhexchar(char c) _const_;
+
+char *hexmem(const void *p, size_t l);
+int unhexmem(const char *p, size_t l, void **mem, size_t *len);
+
+char base32hexchar(int x) _const_;
+int unbase32hexchar(char c) _const_;
+
+char base64char(int x) _const_;
+int unbase64char(char c) _const_;
+
+char *base32hexmem(const void *p, size_t l, bool padding);
+int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len);
+
+char *base64mem(const void *p, size_t l);
+int unbase64mem(const char *p, size_t l, void **mem, size_t *len);
+
+void hexdump(FILE *f, const void *p, size_t s);
diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c
index 7d058416e5..ea0528c6fc 100644
--- a/src/basic/hostname-util.c
+++ b/src/basic/hostname-util.c
@@ -23,6 +23,7 @@
#include <sys/utsname.h>
#include "fd-util.h"
+#include "fileio.h"
#include "hostname-util.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c
index d88864b598..f4e24121e7 100644
--- a/src/basic/in-addr-util.c
+++ b/src/basic/in-addr-util.c
@@ -21,6 +21,7 @@
#include <arpa/inet.h>
+#include "alloc-util.h"
#include "in-addr-util.h"
int in_addr_is_null(int family, const union in_addr_union *u) {
diff --git a/src/basic/io-util.h b/src/basic/io-util.h
index ff7c2a9ac4..cd2aa75ad2 100644
--- a/src/basic/io-util.h
+++ b/src/basic/io-util.h
@@ -21,8 +21,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/uio.h>
#include "time-util.h"
@@ -37,3 +38,39 @@ int pipe_eof(int fd);
int fd_wait_for_event(int fd, int event, usec_t timeout);
ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length);
+
+#define IOVEC_SET_STRING(i, s) \
+ do { \
+ struct iovec *_i = &(i); \
+ char *_s = (char *)(s); \
+ _i->iov_base = _s; \
+ _i->iov_len = strlen(_s); \
+ } while(false)
+
+static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
+ unsigned j;
+ size_t r = 0;
+
+ for (j = 0; j < n; j++)
+ r += i[j].iov_len;
+
+ return r;
+}
+
+static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
+ unsigned j;
+
+ for (j = 0; j < n; j++) {
+ size_t sub;
+
+ if (_unlikely_(k <= 0))
+ break;
+
+ sub = MIN(i[j].iov_len, k);
+ i[j].iov_len -= sub;
+ i[j].iov_base = (uint8_t*) i[j].iov_base + sub;
+ k -= sub;
+ }
+
+ return k;
+}
diff --git a/src/basic/json.c b/src/basic/json.c
index 2b634aa7f8..716705e5ff 100644
--- a/src/basic/json.c
+++ b/src/basic/json.c
@@ -22,10 +22,12 @@
#include <math.h>
#include <sys/types.h>
+#include "alloc-util.h"
+#include "json.h"
#include "macro.h"
+#include "hexdecoct.h"
#include "string-util.h"
#include "utf8.h"
-#include "json.h"
int json_variant_new(JsonVariant **ret, JsonVariantType type) {
JsonVariant *v;
diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c
index 44e1628664..b87fd7670b 100644
--- a/src/basic/locale-util.c
+++ b/src/basic/locale-util.c
@@ -19,11 +19,16 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <langinfo.h>
+#include <locale.h>
#include <sys/mman.h>
+#include "dirent-util.h"
#include "fd-util.h"
#include "locale-util.h"
+#include "path-util.h"
#include "set.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
@@ -205,6 +210,88 @@ bool locale_is_valid(const char *name) {
return true;
}
+void init_gettext(void) {
+ setlocale(LC_ALL, "");
+ textdomain(GETTEXT_PACKAGE);
+}
+
+bool is_locale_utf8(void) {
+ const char *set;
+ static int cached_answer = -1;
+
+ /* Note that we default to 'true' here, since today UTF8 is
+ * pretty much supported everywhere. */
+
+ if (cached_answer >= 0)
+ goto out;
+
+ if (!setlocale(LC_ALL, "")) {
+ cached_answer = true;
+ goto out;
+ }
+
+ set = nl_langinfo(CODESET);
+ if (!set) {
+ cached_answer = true;
+ goto out;
+ }
+
+ if (streq(set, "UTF-8")) {
+ cached_answer = true;
+ goto out;
+ }
+
+ /* For LC_CTYPE=="C" return true, because CTYPE is effectly
+ * unset and everything can do to UTF-8 nowadays. */
+ set = setlocale(LC_CTYPE, NULL);
+ if (!set) {
+ cached_answer = true;
+ goto out;
+ }
+
+ /* Check result, but ignore the result if C was set
+ * explicitly. */
+ cached_answer =
+ STR_IN_SET(set, "C", "POSIX") &&
+ !getenv("LC_ALL") &&
+ !getenv("LC_CTYPE") &&
+ !getenv("LANG");
+
+out:
+ return (bool) cached_answer;
+}
+
+
+const char *draw_special_char(DrawSpecialChar ch) {
+
+ static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
+
+ /* UTF-8 */ {
+ [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */
+ [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
+ [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
+ [DRAW_TREE_SPACE] = " ", /* */
+ [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */
+ [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */
+ [DRAW_ARROW] = "\342\206\222", /* → */
+ [DRAW_DASH] = "\342\200\223", /* – */
+ },
+
+ /* ASCII fallback */ {
+ [DRAW_TREE_VERTICAL] = "| ",
+ [DRAW_TREE_BRANCH] = "|-",
+ [DRAW_TREE_RIGHT] = "`-",
+ [DRAW_TREE_SPACE] = " ",
+ [DRAW_TRIANGULAR_BULLET] = ">",
+ [DRAW_BLACK_CIRCLE] = "*",
+ [DRAW_ARROW] = "->",
+ [DRAW_DASH] = "-",
+ }
+ };
+
+ return draw_table[!is_locale_utf8()][ch];
+}
+
static const char * const locale_variable_table[_VARIABLE_LC_MAX] = {
[VARIABLE_LANG] = "LANG",
[VARIABLE_LANGUAGE] = "LANGUAGE",
diff --git a/src/basic/locale-util.h b/src/basic/locale-util.h
index e48aa3d9af..c71d145139 100644
--- a/src/basic/locale-util.h
+++ b/src/basic/locale-util.h
@@ -21,6 +21,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <libintl.h>
#include <stdbool.h>
#include "macro.h"
@@ -50,5 +51,25 @@ typedef enum LocaleVariable {
int get_locales(char ***l);
bool locale_is_valid(const char *name);
+#define _(String) gettext(String)
+#define N_(String) String
+void init_gettext(void);
+
+bool is_locale_utf8(void);
+
+typedef enum DrawSpecialChar {
+ DRAW_TREE_VERTICAL,
+ DRAW_TREE_BRANCH,
+ DRAW_TREE_RIGHT,
+ DRAW_TREE_SPACE,
+ DRAW_TRIANGULAR_BULLET,
+ DRAW_BLACK_CIRCLE,
+ DRAW_ARROW,
+ DRAW_DASH,
+ _DRAW_SPECIAL_CHAR_MAX
+} DrawSpecialChar;
+
+const char *draw_special_char(DrawSpecialChar ch);
+
const char* locale_variable_to_string(LocaleVariable i) _const_;
LocaleVariable locale_variable_from_string(const char *s) _pure_;
diff --git a/src/basic/lockfile-util.c b/src/basic/lockfile-util.c
index e573dcb56f..87c3aef7af 100644
--- a/src/basic/lockfile-util.c
+++ b/src/basic/lockfile-util.c
@@ -27,9 +27,12 @@
#include <limits.h>
#include <sys/file.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "lockfile-util.h"
+#include "path-util.h"
#include "util.h"
int make_lock_file(const char *p, int operation, LockFile *ret) {
diff --git a/src/basic/log.c b/src/basic/log.c
index 99dccb1f10..1582fce61c 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -31,15 +31,22 @@
#include "sd-messages.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "formats-util.h"
+#include "io-util.h"
#include "log.h"
#include "macro.h"
#include "missing.h"
+#include "parse-util.h"
+#include "proc-cmdline.h"
#include "process-util.h"
#include "signal-util.h"
#include "socket-util.h"
+#include "stdio-util.h"
+#include "string-table.h"
#include "string-util.h"
+#include "syslog-util.h"
#include "terminal-util.h"
#include "util.h"
diff --git a/src/basic/macro.h b/src/basic/macro.h
index f55d65e2f1..daa7c416f7 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -22,11 +22,10 @@
***/
#include <assert.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/uio.h>
#include <inttypes.h>
#include <stdbool.h>
+#include <sys/param.h>
+#include <sys/types.h>
#define _printf_(a,b) __attribute__ ((format (printf, a, b)))
#define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
@@ -295,111 +294,10 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
#define PTR_TO_SIZE(p) ((size_t) ((uintptr_t) (p)))
#define SIZE_TO_PTR(u) ((void *) ((uintptr_t) (u)))
-/* The following macros add 1 when converting things, since UID 0 is a
- * valid UID, while the pointer NULL is special */
-#define PTR_TO_UID(p) ((uid_t) (((uintptr_t) (p))-1))
-#define UID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
-
-#define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1))
-#define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
-
-#define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p))
-#define PID_TO_PTR(p) ((void*) ((uintptr_t) p))
-
-#define memzero(x,l) (memset((x), 0, (l)))
-#define zero(x) (memzero(&(x), sizeof(x)))
-
#define CHAR_TO_STR(x) ((char[2]) { x, 0 })
#define char_array_0(x) x[sizeof(x)-1] = 0;
-#define IOVEC_SET_STRING(i, s) \
- do { \
- struct iovec *_i = &(i); \
- char *_s = (char *)(s); \
- _i->iov_base = _s; \
- _i->iov_len = strlen(_s); \
- } while(false)
-
-static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
- unsigned j;
- size_t r = 0;
-
- for (j = 0; j < n; j++)
- r += i[j].iov_len;
-
- return r;
-}
-
-static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
- unsigned j;
-
- for (j = 0; j < n; j++) {
- size_t sub;
-
- if (_unlikely_(k <= 0))
- break;
-
- sub = MIN(i[j].iov_len, k);
- i[j].iov_len -= sub;
- i[j].iov_base = (uint8_t*) i[j].iov_base + sub;
- k -= sub;
- }
-
- return k;
-}
-
-#define VA_FORMAT_ADVANCE(format, ap) \
-do { \
- int _argtypes[128]; \
- size_t _i, _k; \
- _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \
- assert(_k < ELEMENTSOF(_argtypes)); \
- for (_i = 0; _i < _k; _i++) { \
- if (_argtypes[_i] & PA_FLAG_PTR) { \
- (void) va_arg(ap, void*); \
- continue; \
- } \
- \
- switch (_argtypes[_i]) { \
- case PA_INT: \
- case PA_INT|PA_FLAG_SHORT: \
- case PA_CHAR: \
- (void) va_arg(ap, int); \
- break; \
- case PA_INT|PA_FLAG_LONG: \
- (void) va_arg(ap, long int); \
- break; \
- case PA_INT|PA_FLAG_LONG_LONG: \
- (void) va_arg(ap, long long int); \
- break; \
- case PA_WCHAR: \
- (void) va_arg(ap, wchar_t); \
- break; \
- case PA_WSTRING: \
- case PA_STRING: \
- case PA_POINTER: \
- (void) va_arg(ap, void*); \
- break; \
- case PA_FLOAT: \
- case PA_DOUBLE: \
- (void) va_arg(ap, double); \
- break; \
- case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: \
- (void) va_arg(ap, long double); \
- break; \
- default: \
- assert_not_reached("Unknown format string argument."); \
- } \
- } \
-} while(false)
-
- /* Because statfs.t_type can be int on some architectures, we have to cast
- * the const magic to the type, otherwise the compiler warns about
- * signed/unsigned comparison, because the magic can be 32 bit unsigned.
- */
-#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
-
/* Returns the number of chars needed to format variables of the
* specified type as a decimal string. Adds in extra space for a
* negative '-' prefix (hence works correctly on signed
@@ -410,6 +308,15 @@ do { \
sizeof(type) <= 4 ? 10 : \
sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
+#define DECIMAL_STR_WIDTH(x) \
+ ({ \
+ typeof(x) _x_ = (x); \
+ unsigned ans = 1; \
+ while (_x_ /= 10) \
+ ans++; \
+ ans; \
+ })
+
#define SET_FLAG(v, flag, b) \
(v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
@@ -466,10 +373,6 @@ do { \
#endif
#endif
-#define UID_INVALID ((uid_t) -1)
-#define GID_INVALID ((gid_t) -1)
-#define MODE_INVALID ((mode_t) -1)
-
#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \
static inline void func##p(type *p) { \
if (*p) \
@@ -477,7 +380,4 @@ do { \
} \
struct __useless_struct_to_allow_trailing_semicolon__
-#define CMSG_FOREACH(cmsg, mh) \
- for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
-
#include "log.h"
diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c
index 9d638b27f0..92630f6b25 100644
--- a/src/basic/memfd-util.c
+++ b/src/basic/memfd-util.c
@@ -27,6 +27,7 @@
#include <sys/mman.h>
#include <sys/prctl.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "memfd-util.h"
#include "missing.h"
diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c
index 7ee4546988..0214c4627e 100644
--- a/src/basic/mkdir.c
+++ b/src/basic/mkdir.c
@@ -22,9 +22,12 @@
#include <string.h>
#include <errno.h>
-#include "util.h"
-#include "path-util.h"
+#include "fs-util.h"
#include "mkdir.h"
+#include "path-util.h"
+#include "stat-util.h"
+#include "user-util.h"
+#include "util.h"
int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir) {
struct stat st;
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
new file mode 100644
index 0000000000..29997b1ce7
--- /dev/null
+++ b/src/basic/mount-util.c
@@ -0,0 +1,529 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/statvfs.h>
+
+#include "alloc-util.h"
+#include "escape.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "mount-util.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "set.h"
+#include "stdio-util.h"
+#include "string-util.h"
+#include "util.h"
+
+static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) {
+ char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
+ _cleanup_free_ char *fdinfo = NULL;
+ _cleanup_close_ int subfd = -1;
+ char *p;
+ int r;
+
+ if ((flags & AT_EMPTY_PATH) && isempty(filename))
+ xsprintf(path, "/proc/self/fdinfo/%i", fd);
+ else {
+ subfd = openat(fd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
+ if (subfd < 0)
+ return -errno;
+
+ xsprintf(path, "/proc/self/fdinfo/%i", subfd);
+ }
+
+ r = read_full_file(path, &fdinfo, NULL);
+ if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */
+ return -EOPNOTSUPP;
+ if (r < 0)
+ return -errno;
+
+ p = startswith(fdinfo, "mnt_id:");
+ if (!p) {
+ p = strstr(fdinfo, "\nmnt_id:");
+ if (!p) /* The mnt_id field is a relatively new addition */
+ return -EOPNOTSUPP;
+
+ p += 8;
+ }
+
+ p += strspn(p, WHITESPACE);
+ p[strcspn(p, WHITESPACE)] = 0;
+
+ return safe_atoi(p, mnt_id);
+}
+
+
+int fd_is_mount_point(int fd, const char *filename, int flags) {
+ union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT;
+ int mount_id = -1, mount_id_parent = -1;
+ bool nosupp = false, check_st_dev = true;
+ struct stat a, b;
+ int r;
+
+ assert(fd >= 0);
+ assert(filename);
+
+ /* First we will try the name_to_handle_at() syscall, which
+ * tells us the mount id and an opaque file "handle". It is
+ * not supported everywhere though (kernel compile-time
+ * option, not all file systems are hooked up). If it works
+ * the mount id is usually good enough to tell us whether
+ * something is a mount point.
+ *
+ * If that didn't work we will try to read the mount id from
+ * /proc/self/fdinfo/<fd>. This is almost as good as
+ * name_to_handle_at(), however, does not return the
+ * opaque file handle. The opaque file handle is pretty useful
+ * to detect the root directory, which we should always
+ * consider a mount point. Hence we use this only as
+ * fallback. Exporting the mnt_id in fdinfo is a pretty recent
+ * kernel addition.
+ *
+ * As last fallback we do traditional fstat() based st_dev
+ * comparisons. This is how things were traditionally done,
+ * but unionfs breaks breaks this since it exposes file
+ * systems with a variety of st_dev reported. Also, btrfs
+ * subvolumes have different st_dev, even though they aren't
+ * real mounts of their own. */
+
+ r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags);
+ if (r < 0) {
+ if (errno == ENOSYS)
+ /* This kernel does not support name_to_handle_at()
+ * fall back to simpler logic. */
+ goto fallback_fdinfo;
+ else if (errno == EOPNOTSUPP)
+ /* This kernel or file system does not support
+ * name_to_handle_at(), hence let's see if the
+ * upper fs supports it (in which case it is a
+ * mount point), otherwise fallback to the
+ * traditional stat() logic */
+ nosupp = true;
+ else
+ return -errno;
+ }
+
+ r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH);
+ if (r < 0) {
+ if (errno == EOPNOTSUPP) {
+ if (nosupp)
+ /* Neither parent nor child do name_to_handle_at()?
+ We have no choice but to fall back. */
+ goto fallback_fdinfo;
+ else
+ /* The parent can't do name_to_handle_at() but the
+ * directory we are interested in can?
+ * If so, it must be a mount point. */
+ return 1;
+ } else
+ return -errno;
+ }
+
+ /* The parent can do name_to_handle_at() but the
+ * directory we are interested in can't? If so, it
+ * must be a mount point. */
+ if (nosupp)
+ return 1;
+
+ /* If the file handle for the directory we are
+ * interested in and its parent are identical, we
+ * assume this is the root directory, which is a mount
+ * point. */
+
+ if (h.handle.handle_bytes == h_parent.handle.handle_bytes &&
+ h.handle.handle_type == h_parent.handle.handle_type &&
+ memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0)
+ return 1;
+
+ return mount_id != mount_id_parent;
+
+fallback_fdinfo:
+ r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id);
+ if (r == -EOPNOTSUPP)
+ goto fallback_fstat;
+ if (r < 0)
+ return r;
+
+ r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent);
+ if (r < 0)
+ return r;
+
+ if (mount_id != mount_id_parent)
+ return 1;
+
+ /* Hmm, so, the mount ids are the same. This leaves one
+ * special case though for the root file system. For that,
+ * let's see if the parent directory has the same inode as we
+ * are interested in. Hence, let's also do fstat() checks now,
+ * too, but avoid the st_dev comparisons, since they aren't
+ * that useful on unionfs mounts. */
+ check_st_dev = false;
+
+fallback_fstat:
+ /* yay for fstatat() taking a different set of flags than the other
+ * _at() above */
+ if (flags & AT_SYMLINK_FOLLOW)
+ flags &= ~AT_SYMLINK_FOLLOW;
+ else
+ flags |= AT_SYMLINK_NOFOLLOW;
+ if (fstatat(fd, filename, &a, flags) < 0)
+ return -errno;
+
+ if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
+ return -errno;
+
+ /* A directory with same device and inode as its parent? Must
+ * be the root directory */
+ if (a.st_dev == b.st_dev &&
+ a.st_ino == b.st_ino)
+ return 1;
+
+ return check_st_dev && (a.st_dev != b.st_dev);
+}
+
+/* flags can be AT_SYMLINK_FOLLOW or 0 */
+int path_is_mount_point(const char *t, int flags) {
+ _cleanup_close_ int fd = -1;
+ _cleanup_free_ char *canonical = NULL, *parent = NULL;
+
+ assert(t);
+
+ if (path_equal(t, "/"))
+ return 1;
+
+ /* we need to resolve symlinks manually, we can't just rely on
+ * fd_is_mount_point() to do that for us; if we have a structure like
+ * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
+ * look at needs to be /usr, not /. */
+ if (flags & AT_SYMLINK_FOLLOW) {
+ canonical = canonicalize_file_name(t);
+ if (!canonical)
+ return -errno;
+
+ t = canonical;
+ }
+
+ parent = dirname_malloc(t);
+ if (!parent)
+ return -ENOMEM;
+
+ fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH);
+ if (fd < 0)
+ return -errno;
+
+ return fd_is_mount_point(fd, basename(t), flags);
+}
+
+int umount_recursive(const char *prefix, int flags) {
+ bool again;
+ int n = 0, r;
+
+ /* Try to umount everything recursively below a
+ * directory. Also, take care of stacked mounts, and keep
+ * unmounting them until they are gone. */
+
+ do {
+ _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
+
+ again = false;
+ r = 0;
+
+ proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
+ if (!proc_self_mountinfo)
+ return -errno;
+
+ for (;;) {
+ _cleanup_free_ char *path = NULL, *p = NULL;
+ int k;
+
+ k = fscanf(proc_self_mountinfo,
+ "%*s " /* (1) mount id */
+ "%*s " /* (2) parent id */
+ "%*s " /* (3) major:minor */
+ "%*s " /* (4) root */
+ "%ms " /* (5) mount point */
+ "%*s" /* (6) mount options */
+ "%*[^-]" /* (7) optional fields */
+ "- " /* (8) separator */
+ "%*s " /* (9) file system type */
+ "%*s" /* (10) mount source */
+ "%*s" /* (11) mount options 2 */
+ "%*[^\n]", /* some rubbish at the end */
+ &path);
+ if (k != 1) {
+ if (k == EOF)
+ break;
+
+ continue;
+ }
+
+ r = cunescape(path, UNESCAPE_RELAX, &p);
+ if (r < 0)
+ return r;
+
+ if (!path_startswith(p, prefix))
+ continue;
+
+ if (umount2(p, flags) < 0) {
+ r = -errno;
+ continue;
+ }
+
+ again = true;
+ n++;
+
+ break;
+ }
+
+ } while (again);
+
+ return r ? r : n;
+}
+
+static int get_mount_flags(const char *path, unsigned long *flags) {
+ struct statvfs buf;
+
+ if (statvfs(path, &buf) < 0)
+ return -errno;
+ *flags = buf.f_flag;
+ return 0;
+}
+
+int bind_remount_recursive(const char *prefix, bool ro) {
+ _cleanup_set_free_free_ Set *done = NULL;
+ _cleanup_free_ char *cleaned = NULL;
+ int r;
+
+ /* Recursively remount a directory (and all its submounts)
+ * read-only or read-write. If the directory is already
+ * mounted, we reuse the mount and simply mark it
+ * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
+ * operation). If it isn't we first make it one. Afterwards we
+ * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all
+ * submounts we can access, too. When mounts are stacked on
+ * the same mount point we only care for each individual
+ * "top-level" mount on each point, as we cannot
+ * influence/access the underlying mounts anyway. We do not
+ * have any effect on future submounts that might get
+ * propagated, they migt be writable. This includes future
+ * submounts that have been triggered via autofs. */
+
+ cleaned = strdup(prefix);
+ if (!cleaned)
+ return -ENOMEM;
+
+ path_kill_slashes(cleaned);
+
+ done = set_new(&string_hash_ops);
+ if (!done)
+ return -ENOMEM;
+
+ for (;;) {
+ _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
+ _cleanup_set_free_free_ Set *todo = NULL;
+ bool top_autofs = false;
+ char *x;
+ unsigned long orig_flags;
+
+ todo = set_new(&string_hash_ops);
+ if (!todo)
+ return -ENOMEM;
+
+ proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
+ if (!proc_self_mountinfo)
+ return -errno;
+
+ for (;;) {
+ _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
+ int k;
+
+ k = fscanf(proc_self_mountinfo,
+ "%*s " /* (1) mount id */
+ "%*s " /* (2) parent id */
+ "%*s " /* (3) major:minor */
+ "%*s " /* (4) root */
+ "%ms " /* (5) mount point */
+ "%*s" /* (6) mount options (superblock) */
+ "%*[^-]" /* (7) optional fields */
+ "- " /* (8) separator */
+ "%ms " /* (9) file system type */
+ "%*s" /* (10) mount source */
+ "%*s" /* (11) mount options (bind mount) */
+ "%*[^\n]", /* some rubbish at the end */
+ &path,
+ &type);
+ if (k != 2) {
+ if (k == EOF)
+ break;
+
+ continue;
+ }
+
+ r = cunescape(path, UNESCAPE_RELAX, &p);
+ if (r < 0)
+ return r;
+
+ /* Let's ignore autofs mounts. If they aren't
+ * triggered yet, we want to avoid triggering
+ * them, as we don't make any guarantees for
+ * future submounts anyway. If they are
+ * already triggered, then we will find
+ * another entry for this. */
+ if (streq(type, "autofs")) {
+ top_autofs = top_autofs || path_equal(cleaned, p);
+ continue;
+ }
+
+ if (path_startswith(p, cleaned) &&
+ !set_contains(done, p)) {
+
+ r = set_consume(todo, p);
+ p = NULL;
+
+ if (r == -EEXIST)
+ continue;
+ if (r < 0)
+ return r;
+ }
+ }
+
+ /* If we have no submounts to process anymore and if
+ * the root is either already done, or an autofs, we
+ * are done */
+ if (set_isempty(todo) &&
+ (top_autofs || set_contains(done, cleaned)))
+ return 0;
+
+ if (!set_contains(done, cleaned) &&
+ !set_contains(todo, cleaned)) {
+ /* The prefix directory itself is not yet a
+ * mount, make it one. */
+ if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
+ return -errno;
+
+ orig_flags = 0;
+ (void) get_mount_flags(cleaned, &orig_flags);
+ orig_flags &= ~MS_RDONLY;
+
+ if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
+ return -errno;
+
+ x = strdup(cleaned);
+ if (!x)
+ return -ENOMEM;
+
+ r = set_consume(done, x);
+ if (r < 0)
+ return r;
+ }
+
+ while ((x = set_steal_first(todo))) {
+
+ r = set_consume(done, x);
+ if (r == -EEXIST || r == 0)
+ continue;
+ if (r < 0)
+ return r;
+
+ /* Try to reuse the original flag set, but
+ * don't care for errors, in case of
+ * obstructed mounts */
+ orig_flags = 0;
+ (void) get_mount_flags(x, &orig_flags);
+ orig_flags &= ~MS_RDONLY;
+
+ if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) {
+
+ /* Deal with mount points that are
+ * obstructed by a later mount */
+
+ if (errno != ENOENT)
+ return -errno;
+ }
+
+ }
+ }
+}
+
+int mount_move_root(const char *path) {
+ assert(path);
+
+ if (chdir(path) < 0)
+ return -errno;
+
+ if (mount(path, "/", NULL, MS_MOVE, NULL) < 0)
+ return -errno;
+
+ if (chroot(".") < 0)
+ return -errno;
+
+ if (chdir("/") < 0)
+ return -errno;
+
+ return 0;
+}
+
+bool fstype_is_network(const char *fstype) {
+ static const char table[] =
+ "afs\0"
+ "cifs\0"
+ "smbfs\0"
+ "sshfs\0"
+ "ncpfs\0"
+ "ncp\0"
+ "nfs\0"
+ "nfs4\0"
+ "gfs\0"
+ "gfs2\0"
+ "glusterfs\0";
+
+ const char *x;
+
+ x = startswith(fstype, "fuse.");
+ if (x)
+ fstype = x;
+
+ return nulstr_contains(table, fstype);
+}
+
+int repeat_unmount(const char *path, int flags) {
+ bool done = false;
+
+ assert(path);
+
+ /* If there are multiple mounts on a mount point, this
+ * removes them all */
+
+ for (;;) {
+ if (umount2(path, flags) < 0) {
+
+ if (errno == EINVAL)
+ return done;
+
+ return -errno;
+ }
+
+ done = true;
+ }
+}
diff --git a/src/basic/mount-util.h b/src/basic/mount-util.h
new file mode 100644
index 0000000000..48954c2d67
--- /dev/null
+++ b/src/basic/mount-util.h
@@ -0,0 +1,52 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <fcntl.h>
+#include <mntent.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "missing.h"
+
+int fd_is_mount_point(int fd, const char *filename, int flags);
+int path_is_mount_point(const char *path, int flags);
+
+int repeat_unmount(const char *path, int flags);
+
+int umount_recursive(const char *target, int flags);
+int bind_remount_recursive(const char *prefix, bool ro);
+
+int mount_move_root(const char *path);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
+#define _cleanup_endmntent_ _cleanup_(endmntentp)
+
+bool fstype_is_network(const char *fstype);
+
+union file_handle_union {
+ struct file_handle handle;
+ char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ];
+};
+
+#define FILE_HANDLE_INIT { .handle.handle_bytes = MAX_HANDLE_SZ }
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
new file mode 100644
index 0000000000..1ee5783680
--- /dev/null
+++ b/src/basic/parse-util.c
@@ -0,0 +1,447 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "extract-word.h"
+#include "parse-util.h"
+#include "string-util.h"
+#include "util.h"
+
+int parse_boolean(const char *v) {
+ assert(v);
+
+ if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
+ return 1;
+ else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
+ return 0;
+
+ return -EINVAL;
+}
+
+int parse_pid(const char *s, pid_t* ret_pid) {
+ unsigned long ul = 0;
+ pid_t pid;
+ int r;
+
+ assert(s);
+ assert(ret_pid);
+
+ r = safe_atolu(s, &ul);
+ if (r < 0)
+ return r;
+
+ pid = (pid_t) ul;
+
+ if ((unsigned long) pid != ul)
+ return -ERANGE;
+
+ if (pid <= 0)
+ return -ERANGE;
+
+ *ret_pid = pid;
+ return 0;
+}
+
+int parse_mode(const char *s, mode_t *ret) {
+ char *x;
+ long l;
+
+ assert(s);
+ assert(ret);
+
+ errno = 0;
+ l = strtol(s, &x, 8);
+ if (errno != 0)
+ return -errno;
+
+ if (!x || x == s || *x)
+ return -EINVAL;
+ if (l < 0 || l > 07777)
+ return -ERANGE;
+
+ *ret = (mode_t) l;
+ return 0;
+}
+
+int parse_size(const char *t, uint64_t base, uint64_t *size) {
+
+ /* Soo, sometimes we want to parse IEC binary suffixes, and
+ * sometimes SI decimal suffixes. This function can parse
+ * both. Which one is the right way depends on the
+ * context. Wikipedia suggests that SI is customary for
+ * hardware metrics and network speeds, while IEC is
+ * customary for most data sizes used by software and volatile
+ * (RAM) memory. Hence be careful which one you pick!
+ *
+ * In either case we use just K, M, G as suffix, and not Ki,
+ * Mi, Gi or so (as IEC would suggest). That's because that's
+ * frickin' ugly. But this means you really need to make sure
+ * to document which base you are parsing when you use this
+ * call. */
+
+ struct table {
+ const char *suffix;
+ unsigned long long factor;
+ };
+
+ static const struct table iec[] = {
+ { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
+ { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
+ { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
+ { "G", 1024ULL*1024ULL*1024ULL },
+ { "M", 1024ULL*1024ULL },
+ { "K", 1024ULL },
+ { "B", 1ULL },
+ { "", 1ULL },
+ };
+
+ static const struct table si[] = {
+ { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
+ { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
+ { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
+ { "G", 1000ULL*1000ULL*1000ULL },
+ { "M", 1000ULL*1000ULL },
+ { "K", 1000ULL },
+ { "B", 1ULL },
+ { "", 1ULL },
+ };
+
+ const struct table *table;
+ const char *p;
+ unsigned long long r = 0;
+ unsigned n_entries, start_pos = 0;
+
+ assert(t);
+ assert(base == 1000 || base == 1024);
+ assert(size);
+
+ if (base == 1000) {
+ table = si;
+ n_entries = ELEMENTSOF(si);
+ } else {
+ table = iec;
+ n_entries = ELEMENTSOF(iec);
+ }
+
+ p = t;
+ do {
+ unsigned long long l, tmp;
+ double frac = 0;
+ char *e;
+ unsigned i;
+
+ p += strspn(p, WHITESPACE);
+ if (*p == '-')
+ return -ERANGE;
+
+ errno = 0;
+ l = strtoull(p, &e, 10);
+ if (errno > 0)
+ return -errno;
+ if (e == p)
+ return -EINVAL;
+
+ if (*e == '.') {
+ e++;
+
+ /* strtoull() itself would accept space/+/- */
+ if (*e >= '0' && *e <= '9') {
+ unsigned long long l2;
+ char *e2;
+
+ l2 = strtoull(e, &e2, 10);
+ if (errno > 0)
+ return -errno;
+
+ /* Ignore failure. E.g. 10.M is valid */
+ frac = l2;
+ for (; e < e2; e++)
+ frac /= 10;
+ }
+ }
+
+ e += strspn(e, WHITESPACE);
+
+ for (i = start_pos; i < n_entries; i++)
+ if (startswith(e, table[i].suffix))
+ break;
+
+ if (i >= n_entries)
+ return -EINVAL;
+
+ if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
+ return -ERANGE;
+
+ tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
+ if (tmp > ULLONG_MAX - r)
+ return -ERANGE;
+
+ r += tmp;
+ if ((unsigned long long) (uint64_t) r != r)
+ return -ERANGE;
+
+ p = e + strlen(table[i].suffix);
+
+ start_pos = i + 1;
+
+ } while (*p);
+
+ *size = r;
+
+ return 0;
+}
+
+int parse_range(const char *t, unsigned *lower, unsigned *upper) {
+ _cleanup_free_ char *word = NULL;
+ unsigned l, u;
+ int r;
+
+ assert(lower);
+ assert(upper);
+
+ /* Extract the lower bound. */
+ r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EINVAL;
+
+ r = safe_atou(word, &l);
+ if (r < 0)
+ return r;
+
+ /* Check for the upper bound and extract it if needed */
+ if (!t)
+ /* Single number with no dashes. */
+ u = l;
+ else if (!*t)
+ /* Trailing dash is an error. */
+ return -EINVAL;
+ else {
+ r = safe_atou(t, &u);
+ if (r < 0)
+ return r;
+ }
+
+ *lower = l;
+ *upper = u;
+ return 0;
+}
+
+char *format_bytes(char *buf, size_t l, uint64_t t) {
+ unsigned i;
+
+ /* This only does IEC units so far */
+
+ static const struct {
+ const char *suffix;
+ uint64_t factor;
+ } table[] = {
+ { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
+ { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
+ { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
+ { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
+ { "M", UINT64_C(1024)*UINT64_C(1024) },
+ { "K", UINT64_C(1024) },
+ };
+
+ if (t == (uint64_t) -1)
+ return NULL;
+
+ for (i = 0; i < ELEMENTSOF(table); i++) {
+
+ if (t >= table[i].factor) {
+ snprintf(buf, l,
+ "%" PRIu64 ".%" PRIu64 "%s",
+ t / table[i].factor,
+ ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
+ table[i].suffix);
+
+ goto finish;
+ }
+ }
+
+ snprintf(buf, l, "%" PRIu64 "B", t);
+
+finish:
+ buf[l-1] = 0;
+ return buf;
+
+}
+
+int safe_atou(const char *s, unsigned *ret_u) {
+ char *x = NULL;
+ unsigned long l;
+
+ assert(s);
+ assert(ret_u);
+
+ errno = 0;
+ l = strtoul(s, &x, 0);
+
+ if (!x || x == s || *x || errno)
+ return errno > 0 ? -errno : -EINVAL;
+
+ if ((unsigned long) (unsigned) l != l)
+ return -ERANGE;
+
+ *ret_u = (unsigned) l;
+ return 0;
+}
+
+int safe_atoi(const char *s, int *ret_i) {
+ char *x = NULL;
+ long l;
+
+ assert(s);
+ assert(ret_i);
+
+ errno = 0;
+ l = strtol(s, &x, 0);
+
+ if (!x || x == s || *x || errno)
+ return errno > 0 ? -errno : -EINVAL;
+
+ if ((long) (int) l != l)
+ return -ERANGE;
+
+ *ret_i = (int) l;
+ return 0;
+}
+
+int safe_atollu(const char *s, long long unsigned *ret_llu) {
+ char *x = NULL;
+ unsigned long long l;
+
+ assert(s);
+ assert(ret_llu);
+
+ errno = 0;
+ l = strtoull(s, &x, 0);
+
+ if (!x || x == s || *x || errno)
+ return errno ? -errno : -EINVAL;
+
+ *ret_llu = l;
+ return 0;
+}
+
+int safe_atolli(const char *s, long long int *ret_lli) {
+ char *x = NULL;
+ long long l;
+
+ assert(s);
+ assert(ret_lli);
+
+ errno = 0;
+ l = strtoll(s, &x, 0);
+
+ if (!x || x == s || *x || errno)
+ return errno ? -errno : -EINVAL;
+
+ *ret_lli = l;
+ return 0;
+}
+
+int safe_atou8(const char *s, uint8_t *ret) {
+ char *x = NULL;
+ unsigned long l;
+
+ assert(s);
+ assert(ret);
+
+ errno = 0;
+ l = strtoul(s, &x, 0);
+
+ if (!x || x == s || *x || errno)
+ return errno > 0 ? -errno : -EINVAL;
+
+ if ((unsigned long) (uint8_t) l != l)
+ return -ERANGE;
+
+ *ret = (uint8_t) l;
+ return 0;
+}
+
+int safe_atou16(const char *s, uint16_t *ret) {
+ char *x = NULL;
+ unsigned long l;
+
+ assert(s);
+ assert(ret);
+
+ errno = 0;
+ l = strtoul(s, &x, 0);
+
+ if (!x || x == s || *x || errno)
+ return errno > 0 ? -errno : -EINVAL;
+
+ if ((unsigned long) (uint16_t) l != l)
+ return -ERANGE;
+
+ *ret = (uint16_t) l;
+ return 0;
+}
+
+int safe_atoi16(const char *s, int16_t *ret) {
+ char *x = NULL;
+ long l;
+
+ assert(s);
+ assert(ret);
+
+ errno = 0;
+ l = strtol(s, &x, 0);
+
+ if (!x || x == s || *x || errno)
+ return errno > 0 ? -errno : -EINVAL;
+
+ if ((long) (int16_t) l != l)
+ return -ERANGE;
+
+ *ret = (int16_t) l;
+ return 0;
+}
+
+int safe_atod(const char *s, double *ret_d) {
+ char *x = NULL;
+ double d = 0;
+ locale_t loc;
+
+ assert(s);
+ assert(ret_d);
+
+ loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
+ if (loc == (locale_t) 0)
+ return -errno;
+
+ errno = 0;
+ d = strtod_l(s, &x, loc);
+
+ if (!x || x == s || *x || errno) {
+ freelocale(loc);
+ return errno ? -errno : -EINVAL;
+ }
+
+ freelocale(loc);
+ *ret_d = (double) d;
+ return 0;
+}
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
new file mode 100644
index 0000000000..0e56848e26
--- /dev/null
+++ b/src/basic/parse-util.h
@@ -0,0 +1,91 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+#include "macro.h"
+
+#define MODE_INVALID ((mode_t) -1)
+
+int parse_boolean(const char *v) _pure_;
+int parse_pid(const char *s, pid_t* ret_pid);
+int parse_mode(const char *s, mode_t *ret);
+
+int parse_size(const char *t, uint64_t base, uint64_t *size);
+int parse_range(const char *t, unsigned *lower, unsigned *upper);
+
+#define FORMAT_BYTES_MAX 8
+char *format_bytes(char *buf, size_t l, uint64_t t);
+
+int safe_atou(const char *s, unsigned *ret_u);
+int safe_atoi(const char *s, int *ret_i);
+int safe_atollu(const char *s, unsigned long long *ret_u);
+int safe_atolli(const char *s, long long int *ret_i);
+
+int safe_atou8(const char *s, uint8_t *ret);
+
+int safe_atou16(const char *s, uint16_t *ret);
+int safe_atoi16(const char *s, int16_t *ret);
+
+static inline int safe_atou32(const char *s, uint32_t *ret_u) {
+ assert_cc(sizeof(uint32_t) == sizeof(unsigned));
+ return safe_atou(s, (unsigned*) ret_u);
+}
+
+static inline int safe_atoi32(const char *s, int32_t *ret_i) {
+ assert_cc(sizeof(int32_t) == sizeof(int));
+ return safe_atoi(s, (int*) ret_i);
+}
+
+static inline int safe_atou64(const char *s, uint64_t *ret_u) {
+ assert_cc(sizeof(uint64_t) == sizeof(unsigned long long));
+ return safe_atollu(s, (unsigned long long*) ret_u);
+}
+
+static inline int safe_atoi64(const char *s, int64_t *ret_i) {
+ assert_cc(sizeof(int64_t) == sizeof(long long int));
+ return safe_atolli(s, (long long int*) ret_i);
+}
+
+#if LONG_MAX == INT_MAX
+static inline int safe_atolu(const char *s, unsigned long *ret_u) {
+ assert_cc(sizeof(unsigned long) == sizeof(unsigned));
+ return safe_atou(s, (unsigned*) ret_u);
+}
+static inline int safe_atoli(const char *s, long int *ret_u) {
+ assert_cc(sizeof(long int) == sizeof(int));
+ return safe_atoi(s, (int*) ret_u);
+}
+#else
+static inline int safe_atolu(const char *s, unsigned long *ret_u) {
+ assert_cc(sizeof(unsigned long) == sizeof(unsigned long long));
+ return safe_atollu(s, (unsigned long long*) ret_u);
+}
+static inline int safe_atoli(const char *s, long int *ret_u) {
+ assert_cc(sizeof(long int) == sizeof(long long int));
+ return safe_atolli(s, (long long int*) ret_u);
+}
+#endif
+
+int safe_atod(const char *s, double *ret_d);
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index 0b8cac8f3e..ec90c432a4 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -27,12 +27,22 @@
#include <sys/statvfs.h>
#include <unistd.h>
+/* When we include libgen.h because we need dirname() we immediately
+ * undefine basename() since libgen.h defines it as a macro to the
+ * POSIX version which is really broken. We prefer GNU basename(). */
+#include <libgen.h>
+#undef basename
+
+#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "log.h"
#include "macro.h"
#include "missing.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
@@ -45,47 +55,6 @@ bool is_path(const char *p) {
return !!strchr(p, '/');
}
-int path_get_parent(const char *path, char **_r) {
- const char *e, *a = NULL, *b = NULL, *p;
- char *r;
- bool slash = false;
-
- assert(path);
- assert(_r);
-
- if (!*path)
- return -EINVAL;
-
- for (e = path; *e; e++) {
-
- if (!slash && *e == '/') {
- a = b;
- b = e;
- slash = true;
- } else if (slash && *e != '/')
- slash = false;
- }
-
- if (*(e-1) == '/')
- p = a;
- else
- p = b;
-
- if (!p)
- return -EINVAL;
-
- if (p == path)
- r = strdup("/");
- else
- r = strndup(path, p-path);
-
- if (!r)
- return -ENOMEM;
-
- *_r = r;
- return 0;
-}
-
int path_split_and_make_absolute(const char *p, char ***ret) {
char **l;
int r;
@@ -95,7 +64,7 @@ int path_split_and_make_absolute(const char *p, char ***ret) {
l = strv_split(p, ":");
if (!l)
- return NULL;
+ return -ENOMEM;
r = path_strv_make_absolute_cwd(l);
if (r < 0) {
@@ -488,243 +457,6 @@ char* path_join(const char *root, const char *path, const char *rest) {
NULL);
}
-static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) {
- char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
- _cleanup_free_ char *fdinfo = NULL;
- _cleanup_close_ int subfd = -1;
- char *p;
- int r;
-
- if ((flags & AT_EMPTY_PATH) && isempty(filename))
- xsprintf(path, "/proc/self/fdinfo/%i", fd);
- else {
- subfd = openat(fd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
- if (subfd < 0)
- return -errno;
-
- xsprintf(path, "/proc/self/fdinfo/%i", subfd);
- }
-
- r = read_full_file(path, &fdinfo, NULL);
- if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */
- return -EOPNOTSUPP;
- if (r < 0)
- return -errno;
-
- p = startswith(fdinfo, "mnt_id:");
- if (!p) {
- p = strstr(fdinfo, "\nmnt_id:");
- if (!p) /* The mnt_id field is a relatively new addition */
- return -EOPNOTSUPP;
-
- p += 8;
- }
-
- p += strspn(p, WHITESPACE);
- p[strcspn(p, WHITESPACE)] = 0;
-
- return safe_atoi(p, mnt_id);
-}
-
-int fd_is_mount_point(int fd, const char *filename, int flags) {
- union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT;
- int mount_id = -1, mount_id_parent = -1;
- bool nosupp = false, check_st_dev = true;
- struct stat a, b;
- int r;
-
- assert(fd >= 0);
- assert(filename);
-
- /* First we will try the name_to_handle_at() syscall, which
- * tells us the mount id and an opaque file "handle". It is
- * not supported everywhere though (kernel compile-time
- * option, not all file systems are hooked up). If it works
- * the mount id is usually good enough to tell us whether
- * something is a mount point.
- *
- * If that didn't work we will try to read the mount id from
- * /proc/self/fdinfo/<fd>. This is almost as good as
- * name_to_handle_at(), however, does not return the
- * opaque file handle. The opaque file handle is pretty useful
- * to detect the root directory, which we should always
- * consider a mount point. Hence we use this only as
- * fallback. Exporting the mnt_id in fdinfo is a pretty recent
- * kernel addition.
- *
- * As last fallback we do traditional fstat() based st_dev
- * comparisons. This is how things were traditionally done,
- * but unionfs breaks breaks this since it exposes file
- * systems with a variety of st_dev reported. Also, btrfs
- * subvolumes have different st_dev, even though they aren't
- * real mounts of their own. */
-
- r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags);
- if (r < 0) {
- if (errno == ENOSYS)
- /* This kernel does not support name_to_handle_at()
- * fall back to simpler logic. */
- goto fallback_fdinfo;
- else if (errno == EOPNOTSUPP)
- /* This kernel or file system does not support
- * name_to_handle_at(), hence let's see if the
- * upper fs supports it (in which case it is a
- * mount point), otherwise fallback to the
- * traditional stat() logic */
- nosupp = true;
- else
- return -errno;
- }
-
- r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH);
- if (r < 0) {
- if (errno == EOPNOTSUPP) {
- if (nosupp)
- /* Neither parent nor child do name_to_handle_at()?
- We have no choice but to fall back. */
- goto fallback_fdinfo;
- else
- /* The parent can't do name_to_handle_at() but the
- * directory we are interested in can?
- * If so, it must be a mount point. */
- return 1;
- } else
- return -errno;
- }
-
- /* The parent can do name_to_handle_at() but the
- * directory we are interested in can't? If so, it
- * must be a mount point. */
- if (nosupp)
- return 1;
-
- /* If the file handle for the directory we are
- * interested in and its parent are identical, we
- * assume this is the root directory, which is a mount
- * point. */
-
- if (h.handle.handle_bytes == h_parent.handle.handle_bytes &&
- h.handle.handle_type == h_parent.handle.handle_type &&
- memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0)
- return 1;
-
- return mount_id != mount_id_parent;
-
-fallback_fdinfo:
- r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id);
- if (r == -EOPNOTSUPP)
- goto fallback_fstat;
- if (r < 0)
- return r;
-
- r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent);
- if (r < 0)
- return r;
-
- if (mount_id != mount_id_parent)
- return 1;
-
- /* Hmm, so, the mount ids are the same. This leaves one
- * special case though for the root file system. For that,
- * let's see if the parent directory has the same inode as we
- * are interested in. Hence, let's also do fstat() checks now,
- * too, but avoid the st_dev comparisons, since they aren't
- * that useful on unionfs mounts. */
- check_st_dev = false;
-
-fallback_fstat:
- /* yay for fstatat() taking a different set of flags than the other
- * _at() above */
- if (flags & AT_SYMLINK_FOLLOW)
- flags &= ~AT_SYMLINK_FOLLOW;
- else
- flags |= AT_SYMLINK_NOFOLLOW;
- if (fstatat(fd, filename, &a, flags) < 0)
- return -errno;
-
- if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
- return -errno;
-
- /* A directory with same device and inode as its parent? Must
- * be the root directory */
- if (a.st_dev == b.st_dev &&
- a.st_ino == b.st_ino)
- return 1;
-
- return check_st_dev && (a.st_dev != b.st_dev);
-}
-
-/* flags can be AT_SYMLINK_FOLLOW or 0 */
-int path_is_mount_point(const char *t, int flags) {
- _cleanup_close_ int fd = -1;
- _cleanup_free_ char *canonical = NULL, *parent = NULL;
- int r;
-
- assert(t);
-
- if (path_equal(t, "/"))
- return 1;
-
- /* we need to resolve symlinks manually, we can't just rely on
- * fd_is_mount_point() to do that for us; if we have a structure like
- * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
- * look at needs to be /usr, not /. */
- if (flags & AT_SYMLINK_FOLLOW) {
- canonical = canonicalize_file_name(t);
- if (!canonical)
- return -errno;
-
- t = canonical;
- }
-
- r = path_get_parent(t, &parent);
- if (r < 0)
- return r;
-
- fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH);
- if (fd < 0)
- return -errno;
-
- return fd_is_mount_point(fd, basename(t), flags);
-}
-
-int path_is_read_only_fs(const char *path) {
- struct statvfs st;
-
- assert(path);
-
- if (statvfs(path, &st) < 0)
- return -errno;
-
- if (st.f_flag & ST_RDONLY)
- return true;
-
- /* On NFS, statvfs() might not reflect whether we can actually
- * write to the remote share. Let's try again with
- * access(W_OK) which is more reliable, at least sometimes. */
- if (access(path, W_OK) < 0 && errno == EROFS)
- return true;
-
- return false;
-}
-
-int path_is_os_tree(const char *path) {
- char *p;
- int r;
-
- /* We use /usr/lib/os-release as flag file if something is an OS */
- p = strjoina(path, "/usr/lib/os-release");
- r = access(p, F_OK);
- if (r >= 0)
- return 1;
-
- /* Also check for the old location in /etc, just in case. */
- p = strjoina(path, "/etc/os-release");
- r = access(p, F_OK);
-
- return r >= 0;
-}
-
int find_binary(const char *name, char **ret) {
int last_error, r;
const char *p;
@@ -936,3 +668,134 @@ int parse_path_argument_and_warn(const char *path, bool suppress_root, char **ar
*arg = p;
return 0;
}
+
+char* dirname_malloc(const char *path) {
+ char *d, *dir, *dir2;
+
+ assert(path);
+
+ d = strdup(path);
+ if (!d)
+ return NULL;
+
+ dir = dirname(d);
+ assert(dir);
+
+ if (dir == d)
+ return d;
+
+ dir2 = strdup(dir);
+ free(d);
+
+ return dir2;
+}
+
+bool filename_is_valid(const char *p) {
+ const char *e;
+
+ if (isempty(p))
+ return false;
+
+ if (streq(p, "."))
+ return false;
+
+ if (streq(p, ".."))
+ return false;
+
+ e = strchrnul(p, '/');
+ if (*e != 0)
+ return false;
+
+ if (e - p > FILENAME_MAX)
+ return false;
+
+ return true;
+}
+
+bool path_is_safe(const char *p) {
+
+ if (isempty(p))
+ return false;
+
+ if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
+ return false;
+
+ if (strlen(p)+1 > PATH_MAX)
+ return false;
+
+ /* The following two checks are not really dangerous, but hey, they still are confusing */
+ if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
+ return false;
+
+ if (strstr(p, "//"))
+ return false;
+
+ return true;
+}
+
+char *file_in_same_dir(const char *path, const char *filename) {
+ char *e, *ret;
+ size_t k;
+
+ assert(path);
+ assert(filename);
+
+ /* This removes the last component of path and appends
+ * filename, unless the latter is absolute anyway or the
+ * former isn't */
+
+ if (path_is_absolute(filename))
+ return strdup(filename);
+
+ e = strrchr(path, '/');
+ if (!e)
+ return strdup(filename);
+
+ k = strlen(filename);
+ ret = new(char, (e + 1 - path) + k + 1);
+ if (!ret)
+ return NULL;
+
+ memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1);
+ return ret;
+}
+
+bool hidden_file_allow_backup(const char *filename) {
+ assert(filename);
+
+ return
+ filename[0] == '.' ||
+ streq(filename, "lost+found") ||
+ streq(filename, "aquota.user") ||
+ streq(filename, "aquota.group") ||
+ endswith(filename, ".rpmnew") ||
+ endswith(filename, ".rpmsave") ||
+ endswith(filename, ".rpmorig") ||
+ endswith(filename, ".dpkg-old") ||
+ endswith(filename, ".dpkg-new") ||
+ endswith(filename, ".dpkg-tmp") ||
+ endswith(filename, ".dpkg-dist") ||
+ endswith(filename, ".dpkg-bak") ||
+ endswith(filename, ".dpkg-backup") ||
+ endswith(filename, ".dpkg-remove") ||
+ endswith(filename, ".swp");
+}
+
+bool hidden_file(const char *filename) {
+ assert(filename);
+
+ if (endswith(filename, "~"))
+ return true;
+
+ return hidden_file_allow_backup(filename);
+}
+
+bool is_device_path(const char *path) {
+
+ /* Returns true on paths that refer to a device, either in
+ * sysfs or in /dev */
+
+ return
+ path_startswith(path, "/dev/") ||
+ path_startswith(path, "/sys/");
+}
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
index 9d4522c8eb..989e0f9004 100644
--- a/src/basic/path-util.h
+++ b/src/basic/path-util.h
@@ -37,7 +37,6 @@
bool is_path(const char *p) _pure_;
int path_split_and_make_absolute(const char *p, char ***ret);
-int path_get_parent(const char *path, char **parent);
bool path_is_absolute(const char *p) _pure_;
char* path_make_absolute(const char *p, const char *prefix);
int path_make_absolute_cwd(const char *p, char **ret);
@@ -53,11 +52,6 @@ int path_strv_make_absolute_cwd(char **l);
char** path_strv_resolve(char **l, const char *prefix);
char** path_strv_resolve_uniq(char **l, const char *prefix);
-int fd_is_mount_point(int fd, const char *filename, int flags);
-int path_is_mount_point(const char *path, int flags);
-int path_is_read_only_fs(const char *path);
-int path_is_os_tree(const char *path);
-
int find_binary(const char *name, char **filename);
bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update);
@@ -103,3 +97,15 @@ char *prefix_root(const char *root, const char *path);
})
int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg);
+
+char* dirname_malloc(const char *path);
+
+bool filename_is_valid(const char *p) _pure_;
+bool path_is_safe(const char *p) _pure_;
+
+char *file_in_same_dir(const char *path, const char *filename);
+
+bool hidden_file_allow_backup(const char *filename);
+bool hidden_file(const char *filename) _pure_;
+
+bool is_device_path(const char *path);
diff --git a/src/basic/prioq.c b/src/basic/prioq.c
index d55b348c22..7590698911 100644
--- a/src/basic/prioq.c
+++ b/src/basic/prioq.c
@@ -29,8 +29,9 @@
* The underlying algorithm used in this implementation is a Heap.
*/
-#include "util.h"
+#include "alloc-util.h"
#include "prioq.h"
+#include "util.h"
struct prioq_item {
void *data;
diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c
new file mode 100644
index 0000000000..dd91ce7dbc
--- /dev/null
+++ b/src/basic/proc-cmdline.c
@@ -0,0 +1,145 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "extract-word.h"
+#include "fileio.h"
+#include "macro.h"
+#include "parse-util.h"
+#include "proc-cmdline.h"
+#include "process-util.h"
+#include "string-util.h"
+#include "util.h"
+#include "virt.h"
+
+int proc_cmdline(char **ret) {
+ assert(ret);
+
+ if (detect_container() > 0)
+ return get_process_cmdline(1, 0, false, ret);
+ else
+ return read_one_line_file("/proc/cmdline", ret);
+}
+
+int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
+ _cleanup_free_ char *line = NULL;
+ const char *p;
+ int r;
+
+ assert(parse_item);
+
+ r = proc_cmdline(&line);
+ if (r < 0)
+ return r;
+
+ p = line;
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ char *value = NULL;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ /* Filter out arguments that are intended only for the
+ * initrd */
+ if (!in_initrd() && startswith(word, "rd."))
+ continue;
+
+ value = strchr(word, '=');
+ if (value)
+ *(value++) = 0;
+
+ r = parse_item(word, value);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+int get_proc_cmdline_key(const char *key, char **value) {
+ _cleanup_free_ char *line = NULL, *ret = NULL;
+ bool found = false;
+ const char *p;
+ int r;
+
+ assert(key);
+
+ r = proc_cmdline(&line);
+ if (r < 0)
+ return r;
+
+ p = line;
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ const char *e;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ /* Filter out arguments that are intended only for the
+ * initrd */
+ if (!in_initrd() && startswith(word, "rd."))
+ continue;
+
+ if (value) {
+ e = startswith(word, key);
+ if (!e)
+ continue;
+
+ r = free_and_strdup(&ret, e);
+ if (r < 0)
+ return r;
+
+ found = true;
+ } else {
+ if (streq(word, key))
+ found = true;
+ }
+ }
+
+ if (value) {
+ *value = ret;
+ ret = NULL;
+ }
+
+ return found;
+
+}
+
+int shall_restore_state(void) {
+ _cleanup_free_ char *value = NULL;
+ int r;
+
+ r = get_proc_cmdline_key("systemd.restore_state=", &value);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return true;
+
+ return parse_boolean(value) != 0;
+}
diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h
new file mode 100644
index 0000000000..ea8277b053
--- /dev/null
+++ b/src/basic/proc-cmdline.h
@@ -0,0 +1,28 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+int proc_cmdline(char **ret);
+int parse_proc_cmdline(int (*parse_word)(const char *key, const char *value));
+int get_proc_cmdline_key(const char *parameter, char **value);
+
+int shall_restore_state(void);
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 72fc82e7cb..7631928d5f 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -20,20 +20,27 @@
#include <assert.h>
#include <ctype.h>
#include <errno.h>
+#include <sched.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
+#include <sys/personality.h>
+#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
+#include "ioprio.h"
#include "log.h"
#include "process-util.h"
#include "signal-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "user-util.h"
#include "util.h"
@@ -178,6 +185,37 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
return 0;
}
+void rename_process(const char name[8]) {
+ assert(name);
+
+ /* This is a like a poor man's setproctitle(). It changes the
+ * comm field, argv[0], and also the glibc's internally used
+ * name of the process. For the first one a limit of 16 chars
+ * applies, to the second one usually one of 10 (i.e. length
+ * of "/sbin/init"), to the third one one of 7 (i.e. length of
+ * "systemd"). If you pass a longer string it will be
+ * truncated */
+
+ prctl(PR_SET_NAME, name);
+
+ if (program_invocation_name)
+ strncpy(program_invocation_name, name, strlen(program_invocation_name));
+
+ if (saved_argc > 0) {
+ int i;
+
+ if (saved_argv[0])
+ strncpy(saved_argv[0], name, strlen(saved_argv[0]));
+
+ for (i = 1; i < saved_argc; i++) {
+ if (!saved_argv[i])
+ break;
+
+ memzero(saved_argv[i], strlen(saved_argv[i]));
+ }
+ }
+}
+
int is_kernel_thread(pid_t pid) {
const char *p;
size_t count;
@@ -368,7 +406,7 @@ int get_process_environ(pid_t pid, char **env) {
return 0;
}
-int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
+int get_process_ppid(pid_t pid, pid_t *_ppid) {
int r;
_cleanup_free_ char *line = NULL;
long unsigned ppid;
@@ -561,9 +599,12 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) {
bool pid_is_unwaited(pid_t pid) {
/* Checks whether a PID is still valid at all, including a zombie */
- if (pid <= 0)
+ if (pid < 0)
return false;
+ if (pid <= 1) /* If we or PID 1 would be dead and have been waited for, this code would not be running */
+ return true;
+
if (kill(pid, 0) >= 0)
return true;
@@ -575,12 +616,141 @@ bool pid_is_alive(pid_t pid) {
/* Checks whether a PID is still valid and not a zombie */
- if (pid <= 0)
+ if (pid < 0)
return false;
+ if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */
+ return true;
+
r = get_process_state(pid);
if (r == -ESRCH || r == 'Z')
return false;
return true;
}
+
+bool is_main_thread(void) {
+ static thread_local int cached = 0;
+
+ if (_unlikely_(cached == 0))
+ cached = getpid() == gettid() ? 1 : -1;
+
+ return cached > 0;
+}
+
+noreturn void freeze(void) {
+
+ /* Make sure nobody waits for us on a socket anymore */
+ close_all_fds(NULL, 0);
+
+ sync();
+
+ for (;;)
+ pause();
+}
+
+bool oom_score_adjust_is_valid(int oa) {
+ return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
+}
+
+unsigned long personality_from_string(const char *p) {
+
+ /* Parse a personality specifier. We introduce our own
+ * identifiers that indicate specific ABIs, rather than just
+ * hints regarding the register size, since we want to keep
+ * things open for multiple locally supported ABIs for the
+ * same register size. We try to reuse the ABI identifiers
+ * used by libseccomp. */
+
+#if defined(__x86_64__)
+
+ if (streq(p, "x86"))
+ return PER_LINUX32;
+
+ if (streq(p, "x86-64"))
+ return PER_LINUX;
+
+#elif defined(__i386__)
+
+ if (streq(p, "x86"))
+ return PER_LINUX;
+
+#elif defined(__s390x__)
+
+ if (streq(p, "s390"))
+ return PER_LINUX32;
+
+ if (streq(p, "s390x"))
+ return PER_LINUX;
+
+#elif defined(__s390__)
+
+ if (streq(p, "s390"))
+ return PER_LINUX;
+#endif
+
+ return PERSONALITY_INVALID;
+}
+
+const char* personality_to_string(unsigned long p) {
+
+#if defined(__x86_64__)
+
+ if (p == PER_LINUX32)
+ return "x86";
+
+ if (p == PER_LINUX)
+ return "x86-64";
+
+#elif defined(__i386__)
+
+ if (p == PER_LINUX)
+ return "x86";
+
+#elif defined(__s390x__)
+
+ if (p == PER_LINUX)
+ return "s390x";
+
+ if (p == PER_LINUX32)
+ return "s390";
+
+#elif defined(__s390__)
+
+ if (p == PER_LINUX)
+ return "s390";
+
+#endif
+
+ return NULL;
+}
+
+static const char *const ioprio_class_table[] = {
+ [IOPRIO_CLASS_NONE] = "none",
+ [IOPRIO_CLASS_RT] = "realtime",
+ [IOPRIO_CLASS_BE] = "best-effort",
+ [IOPRIO_CLASS_IDLE] = "idle"
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
+
+static const char *const sigchld_code_table[] = {
+ [CLD_EXITED] = "exited",
+ [CLD_KILLED] = "killed",
+ [CLD_DUMPED] = "dumped",
+ [CLD_TRAPPED] = "trapped",
+ [CLD_STOPPED] = "stopped",
+ [CLD_CONTINUED] = "continued",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
+
+static const char* const sched_policy_table[] = {
+ [SCHED_OTHER] = "other",
+ [SCHED_BATCH] = "batch",
+ [SCHED_IDLE] = "idle",
+ [SCHED_FIFO] = "fifo",
+ [SCHED_RR] = "rr"
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index 2c0d1af000..72633ebf70 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -27,6 +27,7 @@
#include <signal.h>
#include "formats-util.h"
+#include "macro.h"
#define procfs_file_alloca(pid, field) \
({ \
@@ -51,6 +52,7 @@ int get_process_capeff(pid_t pid, char **capeff);
int get_process_cwd(pid_t pid, char **cwd);
int get_process_root(pid_t pid, char **root);
int get_process_environ(pid_t pid, char **environ);
+int get_process_ppid(pid_t pid, pid_t *ppid);
int wait_for_terminate(pid_t pid, siginfo_t *status);
int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
@@ -59,10 +61,39 @@ void sigkill_wait(pid_t *pid);
#define _cleanup_sigkill_wait_ _cleanup_(sigkill_wait)
int kill_and_sigcont(pid_t pid, int sig);
-pid_t get_parent_of_pid(pid_t pid, pid_t *ppid);
+
void rename_process(const char name[8]);
int is_kernel_thread(pid_t pid);
+
int getenv_for_pid(pid_t pid, const char *field, char **_value);
bool pid_is_alive(pid_t pid);
bool pid_is_unwaited(pid_t pid);
+
+bool is_main_thread(void);
+
+noreturn void freeze(void);
+
+bool oom_score_adjust_is_valid(int oa);
+
+#ifndef PERSONALITY_INVALID
+/* personality(7) documents that 0xffffffffUL is used for querying the
+ * current personality, hence let's use that here as error
+ * indicator. */
+#define PERSONALITY_INVALID 0xffffffffLU
+#endif
+
+unsigned long personality_from_string(const char *p);
+const char *personality_to_string(unsigned long);
+
+int ioprio_class_to_string_alloc(int i, char **s);
+int ioprio_class_from_string(const char *s);
+
+const char *sigchld_code_to_string(int i) _const_;
+int sigchld_code_from_string(const char *s) _pure_;
+
+int sched_policy_to_string_alloc(int i, char **s);
+int sched_policy_from_string(const char *s);
+
+#define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p))
+#define PID_TO_PTR(p) ((void*) ((uintptr_t) p))
diff --git a/src/basic/replace-var.c b/src/basic/replace-var.c
index 478fc43a38..18b49a9227 100644
--- a/src/basic/replace-var.c
+++ b/src/basic/replace-var.c
@@ -21,6 +21,7 @@
#include <string.h>
+#include "alloc-util.h"
#include "macro.h"
#include "util.h"
#include "replace-var.h"
diff --git a/src/basic/rlimit-util.c b/src/basic/rlimit-util.c
new file mode 100644
index 0000000000..2627c813fc
--- /dev/null
+++ b/src/basic/rlimit-util.c
@@ -0,0 +1,70 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "missing.h"
+#include "rlimit-util.h"
+#include "string-table.h"
+#include "util.h"
+
+int setrlimit_closest(int resource, const struct rlimit *rlim) {
+ struct rlimit highest, fixed;
+
+ assert(rlim);
+
+ if (setrlimit(resource, rlim) >= 0)
+ return 0;
+
+ if (errno != EPERM)
+ return -errno;
+
+ /* So we failed to set the desired setrlimit, then let's try
+ * to get as close as we can */
+ assert_se(getrlimit(resource, &highest) == 0);
+
+ fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
+ fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
+
+ if (setrlimit(resource, &fixed) < 0)
+ return -errno;
+
+ return 0;
+}
+
+static const char* const rlimit_table[_RLIMIT_MAX] = {
+ [RLIMIT_CPU] = "LimitCPU",
+ [RLIMIT_FSIZE] = "LimitFSIZE",
+ [RLIMIT_DATA] = "LimitDATA",
+ [RLIMIT_STACK] = "LimitSTACK",
+ [RLIMIT_CORE] = "LimitCORE",
+ [RLIMIT_RSS] = "LimitRSS",
+ [RLIMIT_NOFILE] = "LimitNOFILE",
+ [RLIMIT_AS] = "LimitAS",
+ [RLIMIT_NPROC] = "LimitNPROC",
+ [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
+ [RLIMIT_LOCKS] = "LimitLOCKS",
+ [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
+ [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
+ [RLIMIT_NICE] = "LimitNICE",
+ [RLIMIT_RTPRIO] = "LimitRTPRIO",
+ [RLIMIT_RTTIME] = "LimitRTTIME"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
diff --git a/src/basic/rlimit-util.h b/src/basic/rlimit-util.h
new file mode 100644
index 0000000000..262f86dd04
--- /dev/null
+++ b/src/basic/rlimit-util.h
@@ -0,0 +1,33 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/resource.h>
+
+#include "macro.h"
+
+const char *rlimit_to_string(int i) _const_;
+int rlimit_from_string(const char *s) _pure_;
+
+int setrlimit_closest(int resource, const struct rlimit *rlim);
+
+#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim })
diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c
index a5daa23f86..8ec7dd75ee 100644
--- a/src/basic/rm-rf.c
+++ b/src/basic/rm-rf.c
@@ -21,8 +21,10 @@
#include "btrfs-util.h"
#include "fd-util.h"
+#include "mount-util.h"
#include "path-util.h"
#include "rm-rf.h"
+#include "stat-util.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
index 7a7dc90e3c..a821a3d5bb 100644
--- a/src/basic/selinux-util.c
+++ b/src/basic/selinux-util.c
@@ -29,6 +29,7 @@
#include <selinux/context.h>
#endif
+#include "alloc-util.h"
#include "strv.h"
#include "path-util.h"
#include "selinux-util.h"
diff --git a/src/basic/signal-util.c b/src/basic/signal-util.c
index 730f99e0af..8038bc891d 100644
--- a/src/basic/signal-util.c
+++ b/src/basic/signal-util.c
@@ -19,11 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "parse-util.h"
+#include "signal-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "util.h"
-#include "signal-util.h"
-
int reset_all_signal_handlers(void) {
static const struct sigaction sa = {
.sa_handler = SIG_DFL,
@@ -268,3 +269,7 @@ int signal_from_string_try_harder(const char *s) {
return signo;
}
+
+void nop_signal_handler(int sig) {
+ /* nothing here */
+}
diff --git a/src/basic/signal-util.h b/src/basic/signal-util.h
index 5e6eb50b07..e7393e2dac 100644
--- a/src/basic/signal-util.h
+++ b/src/basic/signal-util.h
@@ -39,3 +39,5 @@ const char *signal_to_string(int i) _const_;
int signal_from_string(const char *s) _pure_;
int signal_from_string_try_harder(const char *s);
+
+void nop_signal_handler(int sig);
diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c
index 5f570ff02a..fcc046098d 100644
--- a/src/basic/smack-util.c
+++ b/src/basic/smack-util.c
@@ -23,11 +23,14 @@
#include <sys/xattr.h>
-#include "util.h"
-#include "process-util.h"
-#include "path-util.h"
+#include "alloc-util.h"
#include "fileio.h"
+#include "path-util.h"
+#include "process-util.h"
#include "smack-util.h"
+#include "string-table.h"
+#include "util.h"
+#include "xattr-util.h"
#ifdef HAVE_SMACK
bool mac_smack_use(void) {
diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c
index 4099ea6f9f..e5d4efc719 100644
--- a/src/basic/socket-label.c
+++ b/src/basic/socket-label.c
@@ -25,6 +25,7 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "macro.h"
#include "missing.h"
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 684ac765f5..1acab1ef95 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -30,14 +30,18 @@
#include <sys/types.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
#include "macro.h"
#include "missing.h"
+#include "parse-util.h"
#include "path-util.h"
#include "socket-util.h"
+#include "string-table.h"
#include "string-util.h"
+#include "user-util.h"
#include "util.h"
int socket_address_parse(SocketAddress *a, const char *s) {
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 8b5410b391..c60f2556af 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -127,3 +127,6 @@ int getpeersec(int fd, char **ret);
int send_one_fd(int transport_fd, int fd, int flags);
int receive_one_fd(int transport_fd, int flags);
+
+#define CMSG_FOREACH(cmsg, mh) \
+ for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c
new file mode 100644
index 0000000000..3bc66b3be7
--- /dev/null
+++ b/src/basic/stat-util.c
@@ -0,0 +1,216 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010-2012 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <fcntl.h>
+#include <linux/magic.h>
+#include <sys/statvfs.h>
+#include <unistd.h>
+
+#include "dirent-util.h"
+#include "fd-util.h"
+#include "macro.h"
+#include "missing.h"
+#include "stat-util.h"
+#include "string-util.h"
+
+int is_symlink(const char *path) {
+ struct stat info;
+
+ assert(path);
+
+ if (lstat(path, &info) < 0)
+ return -errno;
+
+ return !!S_ISLNK(info.st_mode);
+}
+
+int is_dir(const char* path, bool follow) {
+ struct stat st;
+ int r;
+
+ assert(path);
+
+ if (follow)
+ r = stat(path, &st);
+ else
+ r = lstat(path, &st);
+ if (r < 0)
+ return -errno;
+
+ return !!S_ISDIR(st.st_mode);
+}
+
+int is_device_node(const char *path) {
+ struct stat info;
+
+ assert(path);
+
+ if (lstat(path, &info) < 0)
+ return -errno;
+
+ return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
+}
+
+int dir_is_empty(const char *path) {
+ _cleanup_closedir_ DIR *d;
+ struct dirent *de;
+
+ d = opendir(path);
+ if (!d)
+ return -errno;
+
+ FOREACH_DIRENT(de, d, return -errno)
+ return 0;
+
+ return 1;
+}
+
+bool null_or_empty(struct stat *st) {
+ assert(st);
+
+ if (S_ISREG(st->st_mode) && st->st_size <= 0)
+ return true;
+
+ /* We don't want to hardcode the major/minor of /dev/null,
+ * hence we do a simpler "is this a device node?" check. */
+
+ if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
+ return true;
+
+ return false;
+}
+
+int null_or_empty_path(const char *fn) {
+ struct stat st;
+
+ assert(fn);
+
+ if (stat(fn, &st) < 0)
+ return -errno;
+
+ return null_or_empty(&st);
+}
+
+int null_or_empty_fd(int fd) {
+ struct stat st;
+
+ assert(fd >= 0);
+
+ if (fstat(fd, &st) < 0)
+ return -errno;
+
+ return null_or_empty(&st);
+}
+
+int path_is_read_only_fs(const char *path) {
+ struct statvfs st;
+
+ assert(path);
+
+ if (statvfs(path, &st) < 0)
+ return -errno;
+
+ if (st.f_flag & ST_RDONLY)
+ return true;
+
+ /* On NFS, statvfs() might not reflect whether we can actually
+ * write to the remote share. Let's try again with
+ * access(W_OK) which is more reliable, at least sometimes. */
+ if (access(path, W_OK) < 0 && errno == EROFS)
+ return true;
+
+ return false;
+}
+
+int path_is_os_tree(const char *path) {
+ char *p;
+ int r;
+
+ assert(path);
+
+ /* We use /usr/lib/os-release as flag file if something is an OS */
+ p = strjoina(path, "/usr/lib/os-release");
+ r = access(p, F_OK);
+ if (r >= 0)
+ return 1;
+
+ /* Also check for the old location in /etc, just in case. */
+ p = strjoina(path, "/etc/os-release");
+ r = access(p, F_OK);
+
+ return r >= 0;
+}
+
+int files_same(const char *filea, const char *fileb) {
+ struct stat a, b;
+
+ assert(filea);
+ assert(fileb);
+
+ if (stat(filea, &a) < 0)
+ return -errno;
+
+ if (stat(fileb, &b) < 0)
+ return -errno;
+
+ return a.st_dev == b.st_dev &&
+ a.st_ino == b.st_ino;
+}
+
+bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
+ assert(s);
+ assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));
+
+ return F_TYPE_EQUAL(s->f_type, magic_value);
+}
+
+int fd_check_fstype(int fd, statfs_f_type_t magic_value) {
+ struct statfs s;
+
+ if (fstatfs(fd, &s) < 0)
+ return -errno;
+
+ return is_fs_type(&s, magic_value);
+}
+
+int path_check_fstype(const char *path, statfs_f_type_t magic_value) {
+ _cleanup_close_ int fd = -1;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return -errno;
+
+ return fd_check_fstype(fd, magic_value);
+}
+
+bool is_temporary_fs(const struct statfs *s) {
+ return is_fs_type(s, TMPFS_MAGIC) ||
+ is_fs_type(s, RAMFS_MAGIC);
+}
+
+int fd_is_temporary_fs(int fd) {
+ struct statfs s;
+
+ if (fstatfs(fd, &s) < 0)
+ return -errno;
+
+ return is_temporary_fs(&s);
+}
diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h
new file mode 100644
index 0000000000..909b220a24
--- /dev/null
+++ b/src/basic/stat-util.h
@@ -0,0 +1,70 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010-2012 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/vfs.h>
+
+#include "macro.h"
+
+int is_symlink(const char *path);
+int is_dir(const char *path, bool follow);
+int is_device_node(const char *path);
+
+int dir_is_empty(const char *path);
+
+static inline int dir_is_populated(const char *path) {
+ int r;
+ r = dir_is_empty(path);
+ if (r < 0)
+ return r;
+ return !r;
+}
+
+bool null_or_empty(struct stat *st) _pure_;
+int null_or_empty_path(const char *fn);
+int null_or_empty_fd(int fd);
+
+int path_is_read_only_fs(const char *path);
+int path_is_os_tree(const char *path);
+
+int files_same(const char *filea, const char *fileb);
+
+/* The .f_type field of struct statfs is really weird defined on
+ * different archs. Let's use our own type we know is sufficiently
+ * larger to store the possible values. */
+typedef long statfs_f_type_t;
+
+bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_;
+int fd_check_fstype(int fd, statfs_f_type_t magic_value);
+int path_check_fstype(const char *path, statfs_f_type_t magic_value);
+
+bool is_temporary_fs(const struct statfs *s) _pure_;
+int fd_is_temporary_fs(int fd);
+
+/* Because statfs.t_type can be int on some architectures, we have to cast
+ * the const magic to the type, otherwise the compiler warns about
+ * signed/unsigned comparison, because the magic can be 32 bit unsigned.
+ */
+#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
diff --git a/src/basic/stdio-util.h b/src/basic/stdio-util.h
new file mode 100644
index 0000000000..b36e8a947e
--- /dev/null
+++ b/src/basic/stdio-util.h
@@ -0,0 +1,78 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <printf.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "macro.h"
+
+#define xsprintf(buf, fmt, ...) \
+ assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), "xsprintf: " #buf "[] must be big enough")
+
+
+#define VA_FORMAT_ADVANCE(format, ap) \
+do { \
+ int _argtypes[128]; \
+ size_t _i, _k; \
+ _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \
+ assert(_k < ELEMENTSOF(_argtypes)); \
+ for (_i = 0; _i < _k; _i++) { \
+ if (_argtypes[_i] & PA_FLAG_PTR) { \
+ (void) va_arg(ap, void*); \
+ continue; \
+ } \
+ \
+ switch (_argtypes[_i]) { \
+ case PA_INT: \
+ case PA_INT|PA_FLAG_SHORT: \
+ case PA_CHAR: \
+ (void) va_arg(ap, int); \
+ break; \
+ case PA_INT|PA_FLAG_LONG: \
+ (void) va_arg(ap, long int); \
+ break; \
+ case PA_INT|PA_FLAG_LONG_LONG: \
+ (void) va_arg(ap, long long int); \
+ break; \
+ case PA_WCHAR: \
+ (void) va_arg(ap, wchar_t); \
+ break; \
+ case PA_WSTRING: \
+ case PA_STRING: \
+ case PA_POINTER: \
+ (void) va_arg(ap, void*); \
+ break; \
+ case PA_FLOAT: \
+ case PA_DOUBLE: \
+ (void) va_arg(ap, double); \
+ break; \
+ case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: \
+ (void) va_arg(ap, long double); \
+ break; \
+ default: \
+ assert_not_reached("Unknown format string argument."); \
+ } \
+ } \
+} while(false)
diff --git a/src/basic/strbuf.c b/src/basic/strbuf.c
index 01a076c2ba..f4f702a05a 100644
--- a/src/basic/strbuf.c
+++ b/src/basic/strbuf.c
@@ -22,8 +22,9 @@
#include <stdlib.h>
#include <string.h>
-#include "util.h"
+#include "alloc-util.h"
#include "strbuf.h"
+#include "util.h"
/*
* Strbuf stores given strings in a single continuous allocated memory
diff --git a/src/basic/string-table.c b/src/basic/string-table.c
new file mode 100644
index 0000000000..a860324fc9
--- /dev/null
+++ b/src/basic/string-table.c
@@ -0,0 +1,35 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "string-table.h"
+
+ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
+ size_t i;
+
+ if (!key)
+ return -1;
+
+ for (i = 0; i < len; ++i)
+ if (streq_ptr(table[i], key))
+ return (ssize_t) i;
+
+ return -1;
+}
diff --git a/src/basic/string-table.h b/src/basic/string-table.h
new file mode 100644
index 0000000000..51b6007214
--- /dev/null
+++ b/src/basic/string-table.h
@@ -0,0 +1,88 @@
+
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "macro.h"
+#include "parse-util.h"
+#include "string-util.h"
+
+ssize_t string_table_lookup(const char * const *table, size_t len, const char *key);
+
+/* For basic lookup tables with strictly enumerated entries */
+#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
+ scope const char *name##_to_string(type i) { \
+ if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \
+ return NULL; \
+ return name##_table[i]; \
+ }
+
+#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
+ scope type name##_from_string(const char *s) { \
+ return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
+ }
+
+#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
+ _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
+ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
+
+/* For string conversions where numbers are also acceptable */
+#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \
+ int name##_to_string_alloc(type i, char **str) { \
+ char *s; \
+ if (i < 0 || i > max) \
+ return -ERANGE; \
+ if (i < (type) ELEMENTSOF(name##_table)) { \
+ s = strdup(name##_table[i]); \
+ if (!s) \
+ return -ENOMEM; \
+ } else { \
+ if (asprintf(&s, "%i", i) < 0) \
+ return -ENOMEM; \
+ } \
+ *str = s; \
+ return 0; \
+ } \
+ type name##_from_string(const char *s) { \
+ type i; \
+ unsigned u = 0; \
+ if (!s) \
+ return (type) -1; \
+ for (i = 0; i < (type) ELEMENTSOF(name##_table); i++) \
+ if (streq_ptr(name##_table[i], s)) \
+ return i; \
+ if (safe_atou(s, &u) >= 0 && u <= max) \
+ return (type) u; \
+ return (type) -1; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
diff --git a/src/basic/string-util.c b/src/basic/string-util.c
index a7cf4e8520..63b9b79df9 100644
--- a/src/basic/string-util.c
+++ b/src/basic/string-util.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "gunicode.h"
#include "utf8.h"
#include "util.h"
@@ -765,3 +766,20 @@ char *string_free_erase(char *s) {
string_erase(s);
return mfree(s);
}
+
+bool string_is_safe(const char *p) {
+ const char *t;
+
+ if (!p)
+ return false;
+
+ for (t = p; *t; t++) {
+ if (*t > 0 && *t < ' ') /* no control characters */
+ return false;
+
+ if (strchr(QUOTES "\\\x7f", *t))
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/basic/string-util.h b/src/basic/string-util.h
index 7b7c0e5f32..297b8f8232 100644
--- a/src/basic/string-util.h
+++ b/src/basic/string-util.h
@@ -168,3 +168,5 @@ void string_erase(char *x);
char *string_free_erase(char *s);
DEFINE_TRIVIAL_CLEANUP_FUNC(char *, string_free_erase);
#define _cleanup_string_free_erase_ _cleanup_(string_free_erasep)
+
+bool string_is_safe(const char *p) _pure_;
diff --git a/src/basic/strv.c b/src/basic/strv.c
index f5df269006..ba6df716a7 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
+#include "alloc-util.h"
#include "escape.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/basic/syslog-util.c b/src/basic/syslog-util.c
new file mode 100644
index 0000000000..01577941a0
--- /dev/null
+++ b/src/basic/syslog-util.c
@@ -0,0 +1,115 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <syslog.h>
+
+#include "assert.h"
+#include "hexdecoct.h"
+#include "string-table.h"
+#include "syslog-util.h"
+
+int syslog_parse_priority(const char **p, int *priority, bool with_facility) {
+ int a = 0, b = 0, c = 0;
+ int k;
+
+ assert(p);
+ assert(*p);
+ assert(priority);
+
+ if ((*p)[0] != '<')
+ return 0;
+
+ if (!strchr(*p, '>'))
+ return 0;
+
+ if ((*p)[2] == '>') {
+ c = undecchar((*p)[1]);
+ k = 3;
+ } else if ((*p)[3] == '>') {
+ b = undecchar((*p)[1]);
+ c = undecchar((*p)[2]);
+ k = 4;
+ } else if ((*p)[4] == '>') {
+ a = undecchar((*p)[1]);
+ b = undecchar((*p)[2]);
+ c = undecchar((*p)[3]);
+ k = 5;
+ } else
+ return 0;
+
+ if (a < 0 || b < 0 || c < 0 ||
+ (!with_facility && (a || b || c > 7)))
+ return 0;
+
+ if (with_facility)
+ *priority = a*100 + b*10 + c;
+ else
+ *priority = (*priority & LOG_FACMASK) | c;
+
+ *p += k;
+ return 1;
+}
+
+static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
+ [LOG_FAC(LOG_KERN)] = "kern",
+ [LOG_FAC(LOG_USER)] = "user",
+ [LOG_FAC(LOG_MAIL)] = "mail",
+ [LOG_FAC(LOG_DAEMON)] = "daemon",
+ [LOG_FAC(LOG_AUTH)] = "auth",
+ [LOG_FAC(LOG_SYSLOG)] = "syslog",
+ [LOG_FAC(LOG_LPR)] = "lpr",
+ [LOG_FAC(LOG_NEWS)] = "news",
+ [LOG_FAC(LOG_UUCP)] = "uucp",
+ [LOG_FAC(LOG_CRON)] = "cron",
+ [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
+ [LOG_FAC(LOG_FTP)] = "ftp",
+ [LOG_FAC(LOG_LOCAL0)] = "local0",
+ [LOG_FAC(LOG_LOCAL1)] = "local1",
+ [LOG_FAC(LOG_LOCAL2)] = "local2",
+ [LOG_FAC(LOG_LOCAL3)] = "local3",
+ [LOG_FAC(LOG_LOCAL4)] = "local4",
+ [LOG_FAC(LOG_LOCAL5)] = "local5",
+ [LOG_FAC(LOG_LOCAL6)] = "local6",
+ [LOG_FAC(LOG_LOCAL7)] = "local7"
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
+
+bool log_facility_unshifted_is_valid(int facility) {
+ return facility >= 0 && facility <= LOG_FAC(~0);
+}
+
+static const char *const log_level_table[] = {
+ [LOG_EMERG] = "emerg",
+ [LOG_ALERT] = "alert",
+ [LOG_CRIT] = "crit",
+ [LOG_ERR] = "err",
+ [LOG_WARNING] = "warning",
+ [LOG_NOTICE] = "notice",
+ [LOG_INFO] = "info",
+ [LOG_DEBUG] = "debug"
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
+
+bool log_level_is_valid(int level) {
+ return level >= 0 && level <= LOG_DEBUG;
+}
diff --git a/src/basic/syslog-util.h b/src/basic/syslog-util.h
new file mode 100644
index 0000000000..eb79c6dbd8
--- /dev/null
+++ b/src/basic/syslog-util.h
@@ -0,0 +1,34 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+
+int log_facility_unshifted_to_string_alloc(int i, char **s);
+int log_facility_unshifted_from_string(const char *s);
+bool log_facility_unshifted_is_valid(int faciliy);
+
+int log_level_to_string_alloc(int i, char **s);
+int log_level_from_string(const char *s);
+bool log_level_is_valid(int level);
+
+int syslog_parse_priority(const char **p, int *priority, bool with_facility);
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index 7dfab0af62..b96bfcb8ef 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -31,12 +31,16 @@
#include <time.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "io-util.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "socket-util.h"
+#include "stat-util.h"
#include "string-util.h"
#include "terminal-util.h"
#include "time-util.h"
@@ -624,84 +628,6 @@ int make_console_stdio(void) {
return 0;
}
-int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
- static const char status_indent[] = " "; /* "[" STATUS "] " */
- _cleanup_free_ char *s = NULL;
- _cleanup_close_ int fd = -1;
- struct iovec iovec[6] = {};
- int n = 0;
- static bool prev_ephemeral;
-
- assert(format);
-
- /* This is independent of logging, as status messages are
- * optional and go exclusively to the console. */
-
- if (vasprintf(&s, format, ap) < 0)
- return log_oom();
-
- fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- if (ellipse) {
- char *e;
- size_t emax, sl;
- int c;
-
- c = fd_columns(fd);
- if (c <= 0)
- c = 80;
-
- sl = status ? sizeof(status_indent)-1 : 0;
-
- emax = c - sl - 1;
- if (emax < 3)
- emax = 3;
-
- e = ellipsize(s, emax, 50);
- if (e) {
- free(s);
- s = e;
- }
- }
-
- if (prev_ephemeral)
- IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
- prev_ephemeral = ephemeral;
-
- if (status) {
- if (!isempty(status)) {
- IOVEC_SET_STRING(iovec[n++], "[");
- IOVEC_SET_STRING(iovec[n++], status);
- IOVEC_SET_STRING(iovec[n++], "] ");
- } else
- IOVEC_SET_STRING(iovec[n++], status_indent);
- }
-
- IOVEC_SET_STRING(iovec[n++], s);
- if (!ephemeral)
- IOVEC_SET_STRING(iovec[n++], "\n");
-
- if (writev(fd, iovec, n) < 0)
- return -errno;
-
- return 0;
-}
-
-int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) {
- va_list ap;
- int r;
-
- assert(format);
-
- va_start(ap, format);
- r = status_vprintf(status, ellipse, ephemeral, format, ap);
- va_end(ap);
-
- return r;
-}
-
bool tty_is_vc(const char *tty) {
assert(tty);
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
index ee0b68b433..f2185c1c11 100644
--- a/src/basic/terminal-util.h
+++ b/src/basic/terminal-util.h
@@ -71,9 +71,6 @@ int make_stdio(int fd);
int make_null_stdio(void);
int make_console_stdio(void);
-int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) _printf_(4,0);
-int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) _printf_(4,5);
-
int fd_columns(int fd);
unsigned columns(void);
int fd_lines(int fd);
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index b348ed4204..9dc280efc6 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -23,7 +23,10 @@
#include <sys/timerfd.h>
#include <sys/timex.h>
+#include "alloc-util.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "path-util.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/basic/umask-util.h b/src/basic/umask-util.h
new file mode 100644
index 0000000000..8ed34658b4
--- /dev/null
+++ b/src/basic/umask-util.h
@@ -0,0 +1,48 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "macro.h"
+
+static inline void umaskp(mode_t *u) {
+ umask(*u);
+}
+
+#define _cleanup_umask_ _cleanup_(umaskp)
+
+struct _umask_struct_ {
+ mode_t mask;
+ bool quit;
+};
+
+static inline void _reset_umask_(struct _umask_struct_ *s) {
+ umask(s->mask);
+};
+
+#define RUN_WITH_UMASK(mask) \
+ for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \
+ !_saved_umask_.quit ; \
+ _saved_umask_.quit = true)
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
index 383c4ab871..0775ae7c14 100644
--- a/src/basic/unit-name.c
+++ b/src/basic/unit-name.c
@@ -22,13 +22,16 @@
#include <errno.h>
#include <string.h>
+#include "alloc-util.h"
#include "bus-label.h"
#include "def.h"
+#include "hexdecoct.h"
#include "path-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
-#include "util.h"
#include "unit-name.h"
+#include "util.h"
#define VALID_CHARS \
DIGITS LETTERS \
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
index 7e6c4c645d..d6c936db37 100644
--- a/src/basic/user-util.c
+++ b/src/basic/user-util.c
@@ -22,11 +22,14 @@
#include <pwd.h>
#include <grp.h>
-#include "user-util.h"
+#include "alloc-util.h"
+#include "fd-util.h"
#include "macro.h"
-#include "util.h"
-#include "string-util.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "string-util.h"
+#include "user-util.h"
+#include "util.h"
bool uid_is_valid(uid_t uid) {
@@ -427,3 +430,43 @@ int reset_uid_gid(void) {
return 0;
}
+
+int take_etc_passwd_lock(const char *root) {
+
+ struct flock flock = {
+ .l_type = F_WRLCK,
+ .l_whence = SEEK_SET,
+ .l_start = 0,
+ .l_len = 0,
+ };
+
+ const char *path;
+ int fd, r;
+
+ /* This is roughly the same as lckpwdf(), but not as awful. We
+ * don't want to use alarm() and signals, hence we implement
+ * our own trivial version of this.
+ *
+ * Note that shadow-utils also takes per-database locks in
+ * addition to lckpwdf(). However, we don't given that they
+ * are redundant as they they invoke lckpwdf() first and keep
+ * it during everything they do. The per-database locks are
+ * awfully racy, and thus we just won't do them. */
+
+ if (root)
+ path = prefix_roota(root, "/etc/.pwd.lock");
+ else
+ path = "/etc/.pwd.lock";
+
+ fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
+ if (fd < 0)
+ return -errno;
+
+ r = fcntl(fd, F_SETLKW, &flock);
+ if (r < 0) {
+ safe_close(fd);
+ return -errno;
+ }
+
+ return fd;
+}
diff --git a/src/basic/user-util.h b/src/basic/user-util.h
index 7995698f27..11ff6674cf 100644
--- a/src/basic/user-util.h
+++ b/src/basic/user-util.h
@@ -52,3 +52,16 @@ int get_home_dir(char **ret);
int get_shell(char **_ret);
int reset_uid_gid(void);
+
+int take_etc_passwd_lock(const char *root);
+
+#define UID_INVALID ((uid_t) -1)
+#define GID_INVALID ((gid_t) -1)
+
+/* The following macros add 1 when converting things, since UID 0 is a
+ * valid UID, while the pointer NULL is special */
+#define PTR_TO_UID(p) ((uid_t) (((uintptr_t) (p))-1))
+#define UID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
+
+#define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1))
+#define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
diff --git a/src/basic/utf8.c b/src/basic/utf8.c
index 800884ffee..7600d99903 100644
--- a/src/basic/utf8.c
+++ b/src/basic/utf8.c
@@ -49,6 +49,8 @@
#include <string.h>
#include <stdbool.h>
+#include "alloc-util.h"
+#include "hexdecoct.h"
#include "utf8.h"
#include "util.h"
diff --git a/src/basic/util.c b/src/basic/util.c
index d5227aa6d0..08bdcd28f2 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -23,7 +23,6 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <glob.h>
#include <grp.h>
#include <langinfo.h>
#include <libintl.h>
@@ -46,7 +45,6 @@
#include <sys/mount.h>
#include <sys/personality.h>
#include <sys/prctl.h>
-#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/time.h>
@@ -54,7 +52,6 @@
#include <sys/utsname.h>
#include <sys/vfs.h>
#include <sys/wait.h>
-#include <sys/xattr.h>
#include <syslog.h>
#include <unistd.h>
@@ -72,6 +69,7 @@
* otherwise conflicts with sys/mount.h. Yay, Linux is great! */
#include <linux/fs.h>
+#include "alloc-util.h"
#include "build.h"
#include "def.h"
#include "device-nodes.h"
@@ -89,11 +87,14 @@
#include "macro.h"
#include "missing.h"
#include "mkdir.h"
+#include "hexdecoct.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "random-util.h"
#include "signal-util.h"
#include "sparse-endian.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
@@ -101,6 +102,8 @@
#include "utf8.h"
#include "util.h"
#include "virt.h"
+#include "dirent-util.h"
+#include "stat-util.h"
/* Put this test here for a lack of better place */
assert_cc(EAGAIN == EWOULDBLOCK);
@@ -122,1571 +125,6 @@ size_t page_size(void) {
return pgsz;
}
-int unlink_noerrno(const char *path) {
- PROTECT_ERRNO;
- int r;
-
- r = unlink(path);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-int parse_boolean(const char *v) {
- assert(v);
-
- if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
- return 1;
- else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off"))
- return 0;
-
- return -EINVAL;
-}
-
-int parse_pid(const char *s, pid_t* ret_pid) {
- unsigned long ul = 0;
- pid_t pid;
- int r;
-
- assert(s);
- assert(ret_pid);
-
- r = safe_atolu(s, &ul);
- if (r < 0)
- return r;
-
- pid = (pid_t) ul;
-
- if ((unsigned long) pid != ul)
- return -ERANGE;
-
- if (pid <= 0)
- return -ERANGE;
-
- *ret_pid = pid;
- return 0;
-}
-
-int safe_atou(const char *s, unsigned *ret_u) {
- char *x = NULL;
- unsigned long l;
-
- assert(s);
- assert(ret_u);
-
- errno = 0;
- l = strtoul(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno > 0 ? -errno : -EINVAL;
-
- if ((unsigned long) (unsigned) l != l)
- return -ERANGE;
-
- *ret_u = (unsigned) l;
- return 0;
-}
-
-int safe_atoi(const char *s, int *ret_i) {
- char *x = NULL;
- long l;
-
- assert(s);
- assert(ret_i);
-
- errno = 0;
- l = strtol(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno > 0 ? -errno : -EINVAL;
-
- if ((long) (int) l != l)
- return -ERANGE;
-
- *ret_i = (int) l;
- return 0;
-}
-
-int safe_atou8(const char *s, uint8_t *ret) {
- char *x = NULL;
- unsigned long l;
-
- assert(s);
- assert(ret);
-
- errno = 0;
- l = strtoul(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno > 0 ? -errno : -EINVAL;
-
- if ((unsigned long) (uint8_t) l != l)
- return -ERANGE;
-
- *ret = (uint8_t) l;
- return 0;
-}
-
-int safe_atou16(const char *s, uint16_t *ret) {
- char *x = NULL;
- unsigned long l;
-
- assert(s);
- assert(ret);
-
- errno = 0;
- l = strtoul(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno > 0 ? -errno : -EINVAL;
-
- if ((unsigned long) (uint16_t) l != l)
- return -ERANGE;
-
- *ret = (uint16_t) l;
- return 0;
-}
-
-int safe_atoi16(const char *s, int16_t *ret) {
- char *x = NULL;
- long l;
-
- assert(s);
- assert(ret);
-
- errno = 0;
- l = strtol(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno > 0 ? -errno : -EINVAL;
-
- if ((long) (int16_t) l != l)
- return -ERANGE;
-
- *ret = (int16_t) l;
- return 0;
-}
-
-int safe_atollu(const char *s, long long unsigned *ret_llu) {
- char *x = NULL;
- unsigned long long l;
-
- assert(s);
- assert(ret_llu);
-
- errno = 0;
- l = strtoull(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno ? -errno : -EINVAL;
-
- *ret_llu = l;
- return 0;
-}
-
-int safe_atolli(const char *s, long long int *ret_lli) {
- char *x = NULL;
- long long l;
-
- assert(s);
- assert(ret_lli);
-
- errno = 0;
- l = strtoll(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno ? -errno : -EINVAL;
-
- *ret_lli = l;
- return 0;
-}
-
-int safe_atod(const char *s, double *ret_d) {
- char *x = NULL;
- double d = 0;
- locale_t loc;
-
- assert(s);
- assert(ret_d);
-
- loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
- if (loc == (locale_t) 0)
- return -errno;
-
- errno = 0;
- d = strtod_l(s, &x, loc);
-
- if (!x || x == s || *x || errno) {
- freelocale(loc);
- return errno ? -errno : -EINVAL;
- }
-
- freelocale(loc);
- *ret_d = (double) d;
- return 0;
-}
-
-
-int fchmod_umask(int fd, mode_t m) {
- mode_t u;
- int r;
-
- u = umask(0777);
- r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
- umask(u);
-
- return r;
-}
-
-int readlinkat_malloc(int fd, const char *p, char **ret) {
- size_t l = 100;
- int r;
-
- assert(p);
- assert(ret);
-
- for (;;) {
- char *c;
- ssize_t n;
-
- c = new(char, l);
- if (!c)
- return -ENOMEM;
-
- n = readlinkat(fd, p, c, l-1);
- if (n < 0) {
- r = -errno;
- free(c);
- return r;
- }
-
- if ((size_t) n < l-1) {
- c[n] = 0;
- *ret = c;
- return 0;
- }
-
- free(c);
- l *= 2;
- }
-}
-
-int readlink_malloc(const char *p, char **ret) {
- return readlinkat_malloc(AT_FDCWD, p, ret);
-}
-
-int readlink_value(const char *p, char **ret) {
- _cleanup_free_ char *link = NULL;
- char *value;
- int r;
-
- r = readlink_malloc(p, &link);
- if (r < 0)
- return r;
-
- value = basename(link);
- if (!value)
- return -ENOENT;
-
- value = strdup(value);
- if (!value)
- return -ENOMEM;
-
- *ret = value;
-
- return 0;
-}
-
-int readlink_and_make_absolute(const char *p, char **r) {
- _cleanup_free_ char *target = NULL;
- char *k;
- int j;
-
- assert(p);
- assert(r);
-
- j = readlink_malloc(p, &target);
- if (j < 0)
- return j;
-
- k = file_in_same_dir(p, target);
- if (!k)
- return -ENOMEM;
-
- *r = k;
- return 0;
-}
-
-int readlink_and_canonicalize(const char *p, char **r) {
- char *t, *s;
- int j;
-
- assert(p);
- assert(r);
-
- j = readlink_and_make_absolute(p, &t);
- if (j < 0)
- return j;
-
- s = canonicalize_file_name(t);
- if (s) {
- free(t);
- *r = s;
- } else
- *r = t;
-
- path_kill_slashes(*r);
-
- return 0;
-}
-
-char *file_in_same_dir(const char *path, const char *filename) {
- char *e, *ret;
- size_t k;
-
- assert(path);
- assert(filename);
-
- /* This removes the last component of path and appends
- * filename, unless the latter is absolute anyway or the
- * former isn't */
-
- if (path_is_absolute(filename))
- return strdup(filename);
-
- e = strrchr(path, '/');
- if (!e)
- return strdup(filename);
-
- k = strlen(filename);
- ret = new(char, (e + 1 - path) + k + 1);
- if (!ret)
- return NULL;
-
- memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1);
- return ret;
-}
-
-int rmdir_parents(const char *path, const char *stop) {
- size_t l;
- int r = 0;
-
- assert(path);
- assert(stop);
-
- l = strlen(path);
-
- /* Skip trailing slashes */
- while (l > 0 && path[l-1] == '/')
- l--;
-
- while (l > 0) {
- char *t;
-
- /* Skip last component */
- while (l > 0 && path[l-1] != '/')
- l--;
-
- /* Skip trailing slashes */
- while (l > 0 && path[l-1] == '/')
- l--;
-
- if (l <= 0)
- break;
-
- if (!(t = strndup(path, l)))
- return -ENOMEM;
-
- if (path_startswith(stop, t)) {
- free(t);
- return 0;
- }
-
- r = rmdir(t);
- free(t);
-
- if (r < 0)
- if (errno != ENOENT)
- return -errno;
- }
-
- return 0;
-}
-
-char hexchar(int x) {
- static const char table[16] = "0123456789abcdef";
-
- return table[x & 15];
-}
-
-int unhexchar(char c) {
-
- if (c >= '0' && c <= '9')
- return c - '0';
-
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
-
- if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
-
- return -EINVAL;
-}
-
-char *hexmem(const void *p, size_t l) {
- char *r, *z;
- const uint8_t *x;
-
- z = r = malloc(l * 2 + 1);
- if (!r)
- return NULL;
-
- for (x = p; x < (const uint8_t*) p + l; x++) {
- *(z++) = hexchar(*x >> 4);
- *(z++) = hexchar(*x & 15);
- }
-
- *z = 0;
- return r;
-}
-
-int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
- _cleanup_free_ uint8_t *r = NULL;
- uint8_t *z;
- const char *x;
-
- assert(mem);
- assert(len);
- assert(p);
-
- z = r = malloc((l + 1) / 2 + 1);
- if (!r)
- return -ENOMEM;
-
- for (x = p; x < p + l; x += 2) {
- int a, b;
-
- a = unhexchar(x[0]);
- if (a < 0)
- return a;
- else if (x+1 < p + l) {
- b = unhexchar(x[1]);
- if (b < 0)
- return b;
- } else
- b = 0;
-
- *(z++) = (uint8_t) a << 4 | (uint8_t) b;
- }
-
- *z = 0;
-
- *mem = r;
- r = NULL;
- *len = (l + 1) / 2;
-
- return 0;
-}
-
-/* https://tools.ietf.org/html/rfc4648#section-6
- * Notice that base32hex differs from base32 in the alphabet it uses.
- * The distinction is that the base32hex representation preserves the
- * order of the underlying data when compared as bytestrings, this is
- * useful when representing NSEC3 hashes, as one can then verify the
- * order of hashes directly from their representation. */
-char base32hexchar(int x) {
- static const char table[32] = "0123456789"
- "ABCDEFGHIJKLMNOPQRSTUV";
-
- return table[x & 31];
-}
-
-int unbase32hexchar(char c) {
- unsigned offset;
-
- if (c >= '0' && c <= '9')
- return c - '0';
-
- offset = '9' - '0' + 1;
-
- if (c >= 'A' && c <= 'V')
- return c - 'A' + offset;
-
- return -EINVAL;
-}
-
-char *base32hexmem(const void *p, size_t l, bool padding) {
- char *r, *z;
- const uint8_t *x;
- size_t len;
-
- if (padding)
- /* five input bytes makes eight output bytes, padding is added so we must round up */
- len = 8 * (l + 4) / 5;
- else {
- /* same, but round down as there is no padding */
- len = 8 * l / 5;
-
- switch (l % 5) {
- case 4:
- len += 7;
- break;
- case 3:
- len += 5;
- break;
- case 2:
- len += 4;
- break;
- case 1:
- len += 2;
- break;
- }
- }
-
- z = r = malloc(len + 1);
- if (!r)
- return NULL;
-
- for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
- /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
- x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
- *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
- *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
- *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
- *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
- *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
- *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
- *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */
- *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */
- }
-
- switch (l % 5) {
- case 4:
- *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
- *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
- *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
- *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
- *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
- *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
- *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */
- if (padding)
- *(z++) = '=';
-
- break;
-
- case 3:
- *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
- *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
- *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
- *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
- *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */
- if (padding) {
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- }
-
- break;
-
- case 2:
- *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
- *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
- *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
- *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */
- if (padding) {
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- }
-
- break;
-
- case 1:
- *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
- *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
- if (padding) {
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- }
-
- break;
- }
-
- *z = 0;
- return r;
-}
-
-int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
- _cleanup_free_ uint8_t *r = NULL;
- int a, b, c, d, e, f, g, h;
- uint8_t *z;
- const char *x;
- size_t len;
- unsigned pad = 0;
-
- assert(p);
-
- /* padding ensures any base32hex input has input divisible by 8 */
- if (padding && l % 8 != 0)
- return -EINVAL;
-
- if (padding) {
- /* strip the padding */
- while (l > 0 && p[l - 1] == '=' && pad < 7) {
- pad ++;
- l --;
- }
- }
-
- /* a group of eight input bytes needs five output bytes, in case of
- padding we need to add some extra bytes */
- len = (l / 8) * 5;
-
- switch (l % 8) {
- case 7:
- len += 4;
- break;
- case 5:
- len += 3;
- break;
- case 4:
- len += 2;
- break;
- case 2:
- len += 1;
- break;
- case 0:
- break;
- default:
- return -EINVAL;
- }
-
- z = r = malloc(len + 1);
- if (!r)
- return -ENOMEM;
-
- for (x = p; x < p + (l / 8) * 8; x += 8) {
- /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
- e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
- a = unbase32hexchar(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase32hexchar(x[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unbase32hexchar(x[2]);
- if (c < 0)
- return -EINVAL;
-
- d = unbase32hexchar(x[3]);
- if (d < 0)
- return -EINVAL;
-
- e = unbase32hexchar(x[4]);
- if (e < 0)
- return -EINVAL;
-
- f = unbase32hexchar(x[5]);
- if (f < 0)
- return -EINVAL;
-
- g = unbase32hexchar(x[6]);
- if (g < 0)
- return -EINVAL;
-
- h = unbase32hexchar(x[7]);
- if (h < 0)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
- *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
- *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
- *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
- *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */
- }
-
- switch (l % 8) {
- case 7:
- a = unbase32hexchar(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase32hexchar(x[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unbase32hexchar(x[2]);
- if (c < 0)
- return -EINVAL;
-
- d = unbase32hexchar(x[3]);
- if (d < 0)
- return -EINVAL;
-
- e = unbase32hexchar(x[4]);
- if (e < 0)
- return -EINVAL;
-
- f = unbase32hexchar(x[5]);
- if (f < 0)
- return -EINVAL;
-
- g = unbase32hexchar(x[6]);
- if (g < 0)
- return -EINVAL;
-
- /* g == 000VV000 */
- if (g & 7)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
- *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
- *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
- *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
-
- break;
- case 5:
- a = unbase32hexchar(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase32hexchar(x[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unbase32hexchar(x[2]);
- if (c < 0)
- return -EINVAL;
-
- d = unbase32hexchar(x[3]);
- if (d < 0)
- return -EINVAL;
-
- e = unbase32hexchar(x[4]);
- if (e < 0)
- return -EINVAL;
-
- /* e == 000SSSS0 */
- if (e & 1)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
- *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
- *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
-
- break;
- case 4:
- a = unbase32hexchar(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase32hexchar(x[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unbase32hexchar(x[2]);
- if (c < 0)
- return -EINVAL;
-
- d = unbase32hexchar(x[3]);
- if (d < 0)
- return -EINVAL;
-
- /* d == 000W0000 */
- if (d & 15)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
- *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
-
- break;
- case 2:
- a = unbase32hexchar(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase32hexchar(x[1]);
- if (b < 0)
- return -EINVAL;
-
- /* b == 000YYY00 */
- if (b & 3)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
-
- break;
- case 0:
- break;
- default:
- return -EINVAL;
- }
-
- *z = 0;
-
- *mem = r;
- r = NULL;
- *_len = len;
-
- return 0;
-}
-
-/* https://tools.ietf.org/html/rfc4648#section-4 */
-char base64char(int x) {
- static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
- return table[x & 63];
-}
-
-int unbase64char(char c) {
- unsigned offset;
-
- if (c >= 'A' && c <= 'Z')
- return c - 'A';
-
- offset = 'Z' - 'A' + 1;
-
- if (c >= 'a' && c <= 'z')
- return c - 'a' + offset;
-
- offset += 'z' - 'a' + 1;
-
- if (c >= '0' && c <= '9')
- return c - '0' + offset;
-
- offset += '9' - '0' + 1;
-
- if (c == '+')
- return offset;
-
- offset ++;
-
- if (c == '/')
- return offset;
-
- return -EINVAL;
-}
-
-char *base64mem(const void *p, size_t l) {
- char *r, *z;
- const uint8_t *x;
-
- /* three input bytes makes four output bytes, padding is added so we must round up */
- z = r = malloc(4 * (l + 2) / 3 + 1);
- if (!r)
- return NULL;
-
- for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
- /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
- *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
- *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
- *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
- *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
- }
-
- switch (l % 3) {
- case 2:
- *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
- *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
- *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
- *(z++) = '=';
-
- break;
- case 1:
- *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
- *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
- *(z++) = '=';
- *(z++) = '=';
-
- break;
- }
-
- *z = 0;
- return r;
-}
-
-int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
- _cleanup_free_ uint8_t *r = NULL;
- int a, b, c, d;
- uint8_t *z;
- const char *x;
- size_t len;
-
- assert(p);
-
- /* padding ensures any base63 input has input divisible by 4 */
- if (l % 4 != 0)
- return -EINVAL;
-
- /* strip the padding */
- if (l > 0 && p[l - 1] == '=')
- l --;
- if (l > 0 && p[l - 1] == '=')
- l --;
-
- /* a group of four input bytes needs three output bytes, in case of
- padding we need to add two or three extra bytes */
- len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0);
-
- z = r = malloc(len + 1);
- if (!r)
- return -ENOMEM;
-
- for (x = p; x < p + (l / 4) * 4; x += 4) {
- /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
- a = unbase64char(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase64char(x[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unbase64char(x[2]);
- if (c < 0)
- return -EINVAL;
-
- d = unbase64char(x[3]);
- if (d < 0)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
- *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
- *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
- }
-
- switch (l % 4) {
- case 3:
- a = unbase64char(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase64char(x[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unbase64char(x[2]);
- if (c < 0)
- return -EINVAL;
-
- /* c == 00ZZZZ00 */
- if (c & 3)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
- *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
-
- break;
- case 2:
- a = unbase64char(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase64char(x[1]);
- if (b < 0)
- return -EINVAL;
-
- /* b == 00YY0000 */
- if (b & 15)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
-
- break;
- case 0:
-
- break;
- default:
- return -EINVAL;
- }
-
- *z = 0;
-
- *mem = r;
- r = NULL;
- *_len = len;
-
- return 0;
-}
-
-char octchar(int x) {
- return '0' + (x & 7);
-}
-
-int unoctchar(char c) {
-
- if (c >= '0' && c <= '7')
- return c - '0';
-
- return -EINVAL;
-}
-
-char decchar(int x) {
- return '0' + (x % 10);
-}
-
-int undecchar(char c) {
-
- if (c >= '0' && c <= '9')
- return c - '0';
-
- return -EINVAL;
-}
-
-_pure_ static bool hidden_file_allow_backup(const char *filename) {
- assert(filename);
-
- return
- filename[0] == '.' ||
- streq(filename, "lost+found") ||
- streq(filename, "aquota.user") ||
- streq(filename, "aquota.group") ||
- endswith(filename, ".rpmnew") ||
- endswith(filename, ".rpmsave") ||
- endswith(filename, ".rpmorig") ||
- endswith(filename, ".dpkg-old") ||
- endswith(filename, ".dpkg-new") ||
- endswith(filename, ".dpkg-tmp") ||
- endswith(filename, ".dpkg-dist") ||
- endswith(filename, ".dpkg-bak") ||
- endswith(filename, ".dpkg-backup") ||
- endswith(filename, ".dpkg-remove") ||
- endswith(filename, ".swp");
-}
-
-bool hidden_file(const char *filename) {
- assert(filename);
-
- if (endswith(filename, "~"))
- return true;
-
- return hidden_file_allow_backup(filename);
-}
-
-bool fstype_is_network(const char *fstype) {
- static const char table[] =
- "afs\0"
- "cifs\0"
- "smbfs\0"
- "sshfs\0"
- "ncpfs\0"
- "ncp\0"
- "nfs\0"
- "nfs4\0"
- "gfs\0"
- "gfs2\0"
- "glusterfs\0";
-
- const char *x;
-
- x = startswith(fstype, "fuse.");
- if (x)
- fstype = x;
-
- return nulstr_contains(table, fstype);
-}
-
-int parse_size(const char *t, uint64_t base, uint64_t *size) {
-
- /* Soo, sometimes we want to parse IEC binary suffixes, and
- * sometimes SI decimal suffixes. This function can parse
- * both. Which one is the right way depends on the
- * context. Wikipedia suggests that SI is customary for
- * hardware metrics and network speeds, while IEC is
- * customary for most data sizes used by software and volatile
- * (RAM) memory. Hence be careful which one you pick!
- *
- * In either case we use just K, M, G as suffix, and not Ki,
- * Mi, Gi or so (as IEC would suggest). That's because that's
- * frickin' ugly. But this means you really need to make sure
- * to document which base you are parsing when you use this
- * call. */
-
- struct table {
- const char *suffix;
- unsigned long long factor;
- };
-
- static const struct table iec[] = {
- { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
- { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
- { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
- { "G", 1024ULL*1024ULL*1024ULL },
- { "M", 1024ULL*1024ULL },
- { "K", 1024ULL },
- { "B", 1ULL },
- { "", 1ULL },
- };
-
- static const struct table si[] = {
- { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
- { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
- { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
- { "G", 1000ULL*1000ULL*1000ULL },
- { "M", 1000ULL*1000ULL },
- { "K", 1000ULL },
- { "B", 1ULL },
- { "", 1ULL },
- };
-
- const struct table *table;
- const char *p;
- unsigned long long r = 0;
- unsigned n_entries, start_pos = 0;
-
- assert(t);
- assert(base == 1000 || base == 1024);
- assert(size);
-
- if (base == 1000) {
- table = si;
- n_entries = ELEMENTSOF(si);
- } else {
- table = iec;
- n_entries = ELEMENTSOF(iec);
- }
-
- p = t;
- do {
- unsigned long long l, tmp;
- double frac = 0;
- char *e;
- unsigned i;
-
- p += strspn(p, WHITESPACE);
- if (*p == '-')
- return -ERANGE;
-
- errno = 0;
- l = strtoull(p, &e, 10);
- if (errno > 0)
- return -errno;
- if (e == p)
- return -EINVAL;
-
- if (*e == '.') {
- e++;
-
- /* strtoull() itself would accept space/+/- */
- if (*e >= '0' && *e <= '9') {
- unsigned long long l2;
- char *e2;
-
- l2 = strtoull(e, &e2, 10);
- if (errno > 0)
- return -errno;
-
- /* Ignore failure. E.g. 10.M is valid */
- frac = l2;
- for (; e < e2; e++)
- frac /= 10;
- }
- }
-
- e += strspn(e, WHITESPACE);
-
- for (i = start_pos; i < n_entries; i++)
- if (startswith(e, table[i].suffix))
- break;
-
- if (i >= n_entries)
- return -EINVAL;
-
- if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
- return -ERANGE;
-
- tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
- if (tmp > ULLONG_MAX - r)
- return -ERANGE;
-
- r += tmp;
- if ((unsigned long long) (uint64_t) r != r)
- return -ERANGE;
-
- p = e + strlen(table[i].suffix);
-
- start_pos = i + 1;
-
- } while (*p);
-
- *size = r;
-
- return 0;
-}
-
-bool is_device_path(const char *path) {
-
- /* Returns true on paths that refer to a device, either in
- * sysfs or in /dev */
-
- return
- path_startswith(path, "/dev/") ||
- path_startswith(path, "/sys/");
-}
-
-int dir_is_empty(const char *path) {
- _cleanup_closedir_ DIR *d;
- struct dirent *de;
-
- d = opendir(path);
- if (!d)
- return -errno;
-
- FOREACH_DIRENT(de, d, return -errno)
- return 0;
-
- return 1;
-}
-
-char* dirname_malloc(const char *path) {
- char *d, *dir, *dir2;
-
- d = strdup(path);
- if (!d)
- return NULL;
- dir = dirname(d);
- assert(dir);
-
- if (dir != d) {
- dir2 = strdup(dir);
- free(d);
- return dir2;
- }
-
- return dir;
-}
-
-void rename_process(const char name[8]) {
- assert(name);
-
- /* This is a like a poor man's setproctitle(). It changes the
- * comm field, argv[0], and also the glibc's internally used
- * name of the process. For the first one a limit of 16 chars
- * applies, to the second one usually one of 10 (i.e. length
- * of "/sbin/init"), to the third one one of 7 (i.e. length of
- * "systemd"). If you pass a longer string it will be
- * truncated */
-
- prctl(PR_SET_NAME, name);
-
- if (program_invocation_name)
- strncpy(program_invocation_name, name, strlen(program_invocation_name));
-
- if (saved_argc > 0) {
- int i;
-
- if (saved_argv[0])
- strncpy(saved_argv[0], name, strlen(saved_argv[0]));
-
- for (i = 1; i < saved_argc; i++) {
- if (!saved_argv[i])
- break;
-
- memzero(saved_argv[i], strlen(saved_argv[i]));
- }
- }
-}
-
-bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
- assert(s);
- assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));
-
- return F_TYPE_EQUAL(s->f_type, magic_value);
-}
-
-int fd_check_fstype(int fd, statfs_f_type_t magic_value) {
- struct statfs s;
-
- if (fstatfs(fd, &s) < 0)
- return -errno;
-
- return is_fs_type(&s, magic_value);
-}
-
-int path_check_fstype(const char *path, statfs_f_type_t magic_value) {
- _cleanup_close_ int fd = -1;
-
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return -errno;
-
- return fd_check_fstype(fd, magic_value);
-}
-
-bool is_temporary_fs(const struct statfs *s) {
- return is_fs_type(s, TMPFS_MAGIC) ||
- is_fs_type(s, RAMFS_MAGIC);
-}
-
-int fd_is_temporary_fs(int fd) {
- struct statfs s;
-
- if (fstatfs(fd, &s) < 0)
- return -errno;
-
- return is_temporary_fs(&s);
-}
-
-int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- assert(path);
-
- /* Under the assumption that we are running privileged we
- * first change the access mode and only then hand out
- * ownership to avoid a window where access is too open. */
-
- if (mode != MODE_INVALID)
- if (chmod(path, mode) < 0)
- return -errno;
-
- if (uid != UID_INVALID || gid != GID_INVALID)
- if (chown(path, uid, gid) < 0)
- return -errno;
-
- return 0;
-}
-
-int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
- assert(fd >= 0);
-
- /* Under the assumption that we are running privileged we
- * first change the access mode and only then hand out
- * ownership to avoid a window where access is too open. */
-
- if (mode != MODE_INVALID)
- if (fchmod(fd, mode) < 0)
- return -errno;
-
- if (uid != UID_INVALID || gid != GID_INVALID)
- if (fchown(fd, uid, gid) < 0)
- return -errno;
-
- return 0;
-}
-
-int files_same(const char *filea, const char *fileb) {
- struct stat a, b;
-
- if (stat(filea, &a) < 0)
- return -errno;
-
- if (stat(fileb, &b) < 0)
- return -errno;
-
- return a.st_dev == b.st_dev &&
- a.st_ino == b.st_ino;
-}
-
-int running_in_chroot(void) {
- int ret;
-
- ret = files_same("/proc/1/root", "/");
- if (ret < 0)
- return ret;
-
- return ret == 0;
-}
-
-int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
- _cleanup_close_ int fd;
- int r;
-
- assert(path);
-
- if (parents)
- mkdir_parents(path, 0755);
-
- fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode > 0 ? mode : 0644);
- if (fd < 0)
- return -errno;
-
- if (mode > 0) {
- r = fchmod(fd, mode);
- if (r < 0)
- return -errno;
- }
-
- if (uid != UID_INVALID || gid != GID_INVALID) {
- r = fchown(fd, uid, gid);
- if (r < 0)
- return -errno;
- }
-
- if (stamp != USEC_INFINITY) {
- struct timespec ts[2];
-
- timespec_store(&ts[0], stamp);
- ts[1] = ts[0];
- r = futimens(fd, ts);
- } else
- r = futimens(fd, NULL);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-int touch(const char *path) {
- return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
-}
-
-static char *unquote(const char *s, const char* quotes) {
- size_t l;
- assert(s);
-
- /* This is rather stupid, simply removes the heading and
- * trailing quotes if there is one. Doesn't care about
- * escaping or anything.
- *
- * DON'T USE THIS FOR NEW CODE ANYMORE!*/
-
- l = strlen(s);
- if (l < 2)
- return strdup(s);
-
- if (strchr(quotes, s[0]) && s[l-1] == s[0])
- return strndup(s+1, l-2);
-
- return strdup(s);
-}
-
-noreturn void freeze(void) {
-
- /* Make sure nobody waits for us on a socket anymore */
- close_all_fds(NULL, 0);
-
- sync();
-
- for (;;)
- pause();
-}
-
-bool null_or_empty(struct stat *st) {
- assert(st);
-
- if (S_ISREG(st->st_mode) && st->st_size <= 0)
- return true;
-
- if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
- return true;
-
- return false;
-}
-
-int null_or_empty_path(const char *fn) {
- struct stat st;
-
- assert(fn);
-
- if (stat(fn, &st) < 0)
- return -errno;
-
- return null_or_empty(&st);
-}
-
-int null_or_empty_fd(int fd) {
- struct stat st;
-
- assert(fd >= 0);
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- return null_or_empty(&st);
-}
-
-DIR *xopendirat(int fd, const char *name, int flags) {
- int nfd;
- DIR *d;
-
- assert(!(flags & O_CREAT));
-
- nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
- if (nfd < 0)
- return NULL;
-
- d = fdopendir(nfd);
- if (!d) {
- safe_close(nfd);
- return NULL;
- }
-
- return d;
-}
-
-static char *tag_to_udev_node(const char *tagvalue, const char *by) {
- _cleanup_free_ char *t = NULL, *u = NULL;
- size_t enc_len;
-
- u = unquote(tagvalue, QUOTES);
- if (!u)
- return NULL;
-
- enc_len = strlen(u) * 4 + 1;
- t = new(char, enc_len);
- if (!t)
- return NULL;
-
- if (encode_devnode_name(u, t, enc_len) < 0)
- return NULL;
-
- return strjoin("/dev/disk/by-", by, "/", t, NULL);
-}
-
-char *fstab_node_to_udev_node(const char *p) {
- assert(p);
-
- if (startswith(p, "LABEL="))
- return tag_to_udev_node(p+6, "label");
-
- if (startswith(p, "UUID="))
- return tag_to_udev_node(p+5, "uuid");
-
- if (startswith(p, "PARTUUID="))
- return tag_to_udev_node(p+9, "partuuid");
-
- if (startswith(p, "PARTLABEL="))
- return tag_to_udev_node(p+10, "partlabel");
-
- return strdup(p);
-}
-
-bool dirent_is_file(const struct dirent *de) {
- assert(de);
-
- if (hidden_file(de->d_name))
- return false;
-
- if (de->d_type != DT_REG &&
- de->d_type != DT_LNK &&
- de->d_type != DT_UNKNOWN)
- return false;
-
- return true;
-}
-
-bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
- assert(de);
-
- if (de->d_type != DT_REG &&
- de->d_type != DT_LNK &&
- de->d_type != DT_UNKNOWN)
- return false;
-
- if (hidden_file_allow_backup(de->d_name))
- return false;
-
- return endswith(de->d_name, suffix);
-}
-
static int do_execute(char **directories, usec_t timeout, char *argv[]) {
_cleanup_hashmap_free_free_ Hashmap *pids = NULL;
_cleanup_set_free_free_ Set *seen = NULL;
@@ -1831,125 +269,6 @@ bool plymouth_running(void) {
return access("/run/plymouth/pid", F_OK) >= 0;
}
-int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
- FILE *f;
- char *t;
- int r, fd;
-
- assert(path);
- assert(_f);
- assert(_temp_path);
-
- r = tempfn_xxxxxx(path, NULL, &t);
- if (r < 0)
- return r;
-
- fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC);
- if (fd < 0) {
- free(t);
- return -errno;
- }
-
- f = fdopen(fd, "we");
- if (!f) {
- unlink_noerrno(t);
- free(t);
- safe_close(fd);
- return -errno;
- }
-
- *_f = f;
- *_temp_path = t;
-
- return 0;
-}
-
-int symlink_atomic(const char *from, const char *to) {
- _cleanup_free_ char *t = NULL;
- int r;
-
- assert(from);
- assert(to);
-
- r = tempfn_random(to, NULL, &t);
- if (r < 0)
- return r;
-
- if (symlink(from, t) < 0)
- return -errno;
-
- if (rename(t, to) < 0) {
- unlink_noerrno(t);
- return -errno;
- }
-
- return 0;
-}
-
-int symlink_idempotent(const char *from, const char *to) {
- _cleanup_free_ char *p = NULL;
- int r;
-
- assert(from);
- assert(to);
-
- if (symlink(from, to) < 0) {
- if (errno != EEXIST)
- return -errno;
-
- r = readlink_malloc(to, &p);
- if (r < 0)
- return r;
-
- if (!streq(p, from))
- return -EINVAL;
- }
-
- return 0;
-}
-
-int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
- _cleanup_free_ char *t = NULL;
- int r;
-
- assert(path);
-
- r = tempfn_random(path, NULL, &t);
- if (r < 0)
- return r;
-
- if (mknod(t, mode, dev) < 0)
- return -errno;
-
- if (rename(t, path) < 0) {
- unlink_noerrno(t);
- return -errno;
- }
-
- return 0;
-}
-
-int mkfifo_atomic(const char *path, mode_t mode) {
- _cleanup_free_ char *t = NULL;
- int r;
-
- assert(path);
-
- r = tempfn_random(path, NULL, &t);
- if (r < 0)
- return r;
-
- if (mkfifo(t, mode) < 0)
- return -errno;
-
- if (rename(t, path) < 0) {
- unlink_noerrno(t);
- return -errno;
- }
-
- return 0;
-}
-
bool display_is_local(const char *display) {
assert(display);
@@ -1984,135 +303,6 @@ int socket_from_display(const char *display, char **path) {
return 0;
}
-int glob_exists(const char *path) {
- _cleanup_globfree_ glob_t g = {};
- int k;
-
- assert(path);
-
- errno = 0;
- k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
-
- if (k == GLOB_NOMATCH)
- return 0;
- else if (k == GLOB_NOSPACE)
- return -ENOMEM;
- else if (k == 0)
- return !strv_isempty(g.gl_pathv);
- else
- return errno ? -errno : -EIO;
-}
-
-int glob_extend(char ***strv, const char *path) {
- _cleanup_globfree_ glob_t g = {};
- int k;
- char **p;
-
- errno = 0;
- k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
-
- if (k == GLOB_NOMATCH)
- return -ENOENT;
- else if (k == GLOB_NOSPACE)
- return -ENOMEM;
- else if (k != 0 || strv_isempty(g.gl_pathv))
- return errno ? -errno : -EIO;
-
- STRV_FOREACH(p, g.gl_pathv) {
- k = strv_extend(strv, *p);
- if (k < 0)
- break;
- }
-
- return k;
-}
-
-int dirent_ensure_type(DIR *d, struct dirent *de) {
- struct stat st;
-
- assert(d);
- assert(de);
-
- if (de->d_type != DT_UNKNOWN)
- return 0;
-
- if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
- return -errno;
-
- de->d_type =
- S_ISREG(st.st_mode) ? DT_REG :
- S_ISDIR(st.st_mode) ? DT_DIR :
- S_ISLNK(st.st_mode) ? DT_LNK :
- S_ISFIFO(st.st_mode) ? DT_FIFO :
- S_ISSOCK(st.st_mode) ? DT_SOCK :
- S_ISCHR(st.st_mode) ? DT_CHR :
- S_ISBLK(st.st_mode) ? DT_BLK :
- DT_UNKNOWN;
-
- return 0;
-}
-
-int get_files_in_directory(const char *path, char ***list) {
- _cleanup_closedir_ DIR *d = NULL;
- size_t bufsize = 0, n = 0;
- _cleanup_strv_free_ char **l = NULL;
-
- assert(path);
-
- /* Returns all files in a directory in *list, and the number
- * of files as return value. If list is NULL returns only the
- * number. */
-
- d = opendir(path);
- if (!d)
- return -errno;
-
- for (;;) {
- struct dirent *de;
-
- errno = 0;
- de = readdir(d);
- if (!de && errno != 0)
- return -errno;
- if (!de)
- break;
-
- dirent_ensure_type(d, de);
-
- if (!dirent_is_file(de))
- continue;
-
- if (list) {
- /* one extra slot is needed for the terminating NULL */
- if (!GREEDY_REALLOC(l, bufsize, n + 2))
- return -ENOMEM;
-
- l[n] = strdup(de->d_name);
- if (!l[n])
- return -ENOMEM;
-
- l[++n] = NULL;
- } else
- n++;
- }
-
- if (list) {
- *list = l;
- l = NULL; /* avoid freeing */
- }
-
- return n;
-}
-
-bool is_main_thread(void) {
- static thread_local int cached = 0;
-
- if (_unlikely_(cached == 0))
- cached = getpid() == gettid() ? 1 : -1;
-
- return cached > 0;
-}
-
int block_get_whole_disk(dev_t d, dev_t *ret) {
char *p, *s;
int r;
@@ -2173,103 +363,6 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
return -ENOENT;
}
-static const char *const ioprio_class_table[] = {
- [IOPRIO_CLASS_NONE] = "none",
- [IOPRIO_CLASS_RT] = "realtime",
- [IOPRIO_CLASS_BE] = "best-effort",
- [IOPRIO_CLASS_IDLE] = "idle"
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
-
-static const char *const sigchld_code_table[] = {
- [CLD_EXITED] = "exited",
- [CLD_KILLED] = "killed",
- [CLD_DUMPED] = "dumped",
- [CLD_TRAPPED] = "trapped",
- [CLD_STOPPED] = "stopped",
- [CLD_CONTINUED] = "continued",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
-
-static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
- [LOG_FAC(LOG_KERN)] = "kern",
- [LOG_FAC(LOG_USER)] = "user",
- [LOG_FAC(LOG_MAIL)] = "mail",
- [LOG_FAC(LOG_DAEMON)] = "daemon",
- [LOG_FAC(LOG_AUTH)] = "auth",
- [LOG_FAC(LOG_SYSLOG)] = "syslog",
- [LOG_FAC(LOG_LPR)] = "lpr",
- [LOG_FAC(LOG_NEWS)] = "news",
- [LOG_FAC(LOG_UUCP)] = "uucp",
- [LOG_FAC(LOG_CRON)] = "cron",
- [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
- [LOG_FAC(LOG_FTP)] = "ftp",
- [LOG_FAC(LOG_LOCAL0)] = "local0",
- [LOG_FAC(LOG_LOCAL1)] = "local1",
- [LOG_FAC(LOG_LOCAL2)] = "local2",
- [LOG_FAC(LOG_LOCAL3)] = "local3",
- [LOG_FAC(LOG_LOCAL4)] = "local4",
- [LOG_FAC(LOG_LOCAL5)] = "local5",
- [LOG_FAC(LOG_LOCAL6)] = "local6",
- [LOG_FAC(LOG_LOCAL7)] = "local7"
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
-
-bool log_facility_unshifted_is_valid(int facility) {
- return facility >= 0 && facility <= LOG_FAC(~0);
-}
-
-static const char *const log_level_table[] = {
- [LOG_EMERG] = "emerg",
- [LOG_ALERT] = "alert",
- [LOG_CRIT] = "crit",
- [LOG_ERR] = "err",
- [LOG_WARNING] = "warning",
- [LOG_NOTICE] = "notice",
- [LOG_INFO] = "info",
- [LOG_DEBUG] = "debug"
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
-
-bool log_level_is_valid(int level) {
- return level >= 0 && level <= LOG_DEBUG;
-}
-
-static const char* const sched_policy_table[] = {
- [SCHED_OTHER] = "other",
- [SCHED_BATCH] = "batch",
- [SCHED_IDLE] = "idle",
- [SCHED_FIFO] = "fifo",
- [SCHED_RR] = "rr"
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
-
-static const char* const rlimit_table[_RLIMIT_MAX] = {
- [RLIMIT_CPU] = "LimitCPU",
- [RLIMIT_FSIZE] = "LimitFSIZE",
- [RLIMIT_DATA] = "LimitDATA",
- [RLIMIT_STACK] = "LimitSTACK",
- [RLIMIT_CORE] = "LimitCORE",
- [RLIMIT_RSS] = "LimitRSS",
- [RLIMIT_NOFILE] = "LimitNOFILE",
- [RLIMIT_AS] = "LimitAS",
- [RLIMIT_NPROC] = "LimitNPROC",
- [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
- [RLIMIT_LOCKS] = "LimitLOCKS",
- [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
- [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
- [RLIMIT_NICE] = "LimitNICE",
- [RLIMIT_RTPRIO] = "LimitRTPRIO",
- [RLIMIT_RTTIME] = "LimitRTTIME"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
-
bool kexec_loaded(void) {
bool loaded = false;
char *s;
@@ -2300,58 +393,6 @@ int prot_from_flags(int flags) {
}
}
-char *format_bytes(char *buf, size_t l, uint64_t t) {
- unsigned i;
-
- static const struct {
- const char *suffix;
- uint64_t factor;
- } table[] = {
- { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
- { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
- { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
- { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
- { "M", UINT64_C(1024)*UINT64_C(1024) },
- { "K", UINT64_C(1024) },
- };
-
- if (t == (uint64_t) -1)
- return NULL;
-
- for (i = 0; i < ELEMENTSOF(table); i++) {
-
- if (t >= table[i].factor) {
- snprintf(buf, l,
- "%" PRIu64 ".%" PRIu64 "%s",
- t / table[i].factor,
- ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
- table[i].suffix);
-
- goto finish;
- }
- }
-
- snprintf(buf, l, "%" PRIu64 "B", t);
-
-finish:
- buf[l-1] = 0;
- return buf;
-
-}
-
-void* memdup(const void *p, size_t l) {
- void *r;
-
- assert(p);
-
- r = malloc(l);
- if (!r)
- return NULL;
-
- memcpy(r, p, l);
- return r;
-}
-
int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
bool stdout_is_tty, stderr_is_tty;
pid_t parent_pid, agent_pid;
@@ -2454,82 +495,6 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
_exit(EXIT_FAILURE);
}
-int setrlimit_closest(int resource, const struct rlimit *rlim) {
- struct rlimit highest, fixed;
-
- assert(rlim);
-
- if (setrlimit(resource, rlim) >= 0)
- return 0;
-
- if (errno != EPERM)
- return -errno;
-
- /* So we failed to set the desired setrlimit, then let's try
- * to get as close as we can */
- assert_se(getrlimit(resource, &highest) == 0);
-
- fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
- fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
-
- if (setrlimit(resource, &fixed) < 0)
- return -errno;
-
- return 0;
-}
-
-bool http_etag_is_valid(const char *etag) {
- if (isempty(etag))
- return false;
-
- if (!endswith(etag, "\""))
- return false;
-
- if (!startswith(etag, "\"") && !startswith(etag, "W/\""))
- return false;
-
- return true;
-}
-
-bool http_url_is_valid(const char *url) {
- const char *p;
-
- if (isempty(url))
- return false;
-
- p = startswith(url, "http://");
- if (!p)
- p = startswith(url, "https://");
- if (!p)
- return false;
-
- if (isempty(p))
- return false;
-
- return ascii_is_valid(p);
-}
-
-bool documentation_url_is_valid(const char *url) {
- const char *p;
-
- if (isempty(url))
- return false;
-
- if (http_url_is_valid(url))
- return true;
-
- p = startswith(url, "file:/");
- if (!p)
- p = startswith(url, "info:");
- if (!p)
- p = startswith(url, "man:");
-
- if (isempty(p))
- return false;
-
- return ascii_is_valid(p);
-}
-
bool in_initrd(void) {
static int saved = -1;
struct statfs s;
@@ -2554,64 +519,6 @@ bool in_initrd(void) {
return saved;
}
-bool filename_is_valid(const char *p) {
-
- if (isempty(p))
- return false;
-
- if (strchr(p, '/'))
- return false;
-
- if (streq(p, "."))
- return false;
-
- if (streq(p, ".."))
- return false;
-
- if (strlen(p) > FILENAME_MAX)
- return false;
-
- return true;
-}
-
-bool string_is_safe(const char *p) {
- const char *t;
-
- if (!p)
- return false;
-
- for (t = p; *t; t++) {
- if (*t > 0 && *t < ' ')
- return false;
-
- if (strchr("\\\"\'\x7f", *t))
- return false;
- }
-
- return true;
-}
-
-bool path_is_safe(const char *p) {
-
- if (isempty(p))
- return false;
-
- if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
- return false;
-
- if (strlen(p)+1 > PATH_MAX)
- return false;
-
- /* The following two checks are not really dangerous, but hey, they still are confusing */
- if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
- return false;
-
- if (strstr(p, "//"))
- return false;
-
- return true;
-}
-
/* hey glibc, APIs with callbacks without a user pointer are so useless */
void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
int (*compar) (const void *, const void *, void *), void *arg) {
@@ -2635,83 +542,6 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
return NULL;
}
-void init_gettext(void) {
- setlocale(LC_ALL, "");
- textdomain(GETTEXT_PACKAGE);
-}
-
-bool is_locale_utf8(void) {
- const char *set;
- static int cached_answer = -1;
-
- if (cached_answer >= 0)
- goto out;
-
- if (!setlocale(LC_ALL, "")) {
- cached_answer = true;
- goto out;
- }
-
- set = nl_langinfo(CODESET);
- if (!set) {
- cached_answer = true;
- goto out;
- }
-
- if (streq(set, "UTF-8")) {
- cached_answer = true;
- goto out;
- }
-
- /* For LC_CTYPE=="C" return true, because CTYPE is effectly
- * unset and everything can do to UTF-8 nowadays. */
- set = setlocale(LC_CTYPE, NULL);
- if (!set) {
- cached_answer = true;
- goto out;
- }
-
- /* Check result, but ignore the result if C was set
- * explicitly. */
- cached_answer =
- STR_IN_SET(set, "C", "POSIX") &&
- !getenv("LC_ALL") &&
- !getenv("LC_CTYPE") &&
- !getenv("LANG");
-
-out:
- return (bool) cached_answer;
-}
-
-const char *draw_special_char(DrawSpecialChar ch) {
- static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
-
- /* UTF-8 */ {
- [DRAW_TREE_VERTICAL] = "\342\224\202 ", /* │ */
- [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
- [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
- [DRAW_TREE_SPACE] = " ", /* */
- [DRAW_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */
- [DRAW_BLACK_CIRCLE] = "\342\227\217", /* ● */
- [DRAW_ARROW] = "\342\206\222", /* → */
- [DRAW_DASH] = "\342\200\223", /* – */
- },
-
- /* ASCII fallback */ {
- [DRAW_TREE_VERTICAL] = "| ",
- [DRAW_TREE_BRANCH] = "|-",
- [DRAW_TREE_RIGHT] = "`-",
- [DRAW_TREE_SPACE] = " ",
- [DRAW_TRIANGULAR_BULLET] = ">",
- [DRAW_BLACK_CIRCLE] = "*",
- [DRAW_ARROW] = "->",
- [DRAW_DASH] = "-",
- }
- };
-
- return draw_table[!is_locale_utf8()][ch];
-}
-
int on_ac_power(void) {
bool found_offline = false, found_online = false;
_cleanup_closedir_ DIR *d = NULL;
@@ -2788,133 +618,6 @@ int on_ac_power(void) {
return found_online || !found_offline;
}
-static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
- char **i;
-
- assert(path);
- assert(mode);
- assert(_f);
-
- if (!path_strv_resolve_uniq(search, root))
- return -ENOMEM;
-
- STRV_FOREACH(i, search) {
- _cleanup_free_ char *p = NULL;
- FILE *f;
-
- if (root)
- p = strjoin(root, *i, "/", path, NULL);
- else
- p = strjoin(*i, "/", path, NULL);
- if (!p)
- return -ENOMEM;
-
- f = fopen(p, mode);
- if (f) {
- *_f = f;
- return 0;
- }
-
- if (errno != ENOENT)
- return -errno;
- }
-
- return -ENOENT;
-}
-
-int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
- _cleanup_strv_free_ char **copy = NULL;
-
- assert(path);
- assert(mode);
- assert(_f);
-
- if (path_is_absolute(path)) {
- FILE *f;
-
- f = fopen(path, mode);
- if (f) {
- *_f = f;
- return 0;
- }
-
- return -errno;
- }
-
- copy = strv_copy((char**) search);
- if (!copy)
- return -ENOMEM;
-
- return search_and_fopen_internal(path, mode, root, copy, _f);
-}
-
-int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
- _cleanup_strv_free_ char **s = NULL;
-
- if (path_is_absolute(path)) {
- FILE *f;
-
- f = fopen(path, mode);
- if (f) {
- *_f = f;
- return 0;
- }
-
- return -errno;
- }
-
- s = strv_split_nulstr(search);
- if (!s)
- return -ENOMEM;
-
- return search_and_fopen_internal(path, mode, root, s, _f);
-}
-
-void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
- size_t a, newalloc;
- void *q;
-
- assert(p);
- assert(allocated);
-
- if (*allocated >= need)
- return *p;
-
- newalloc = MAX(need * 2, 64u / size);
- a = newalloc * size;
-
- /* check for overflows */
- if (a < size * need)
- return NULL;
-
- q = realloc(*p, a);
- if (!q)
- return NULL;
-
- *p = q;
- *allocated = newalloc;
- return q;
-}
-
-void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
- size_t prev;
- uint8_t *q;
-
- assert(p);
- assert(allocated);
-
- prev = *allocated;
-
- q = greedy_realloc(p, allocated, need, size);
- if (!q)
- return NULL;
-
- if (*allocated > prev)
- memzero(q + prev * size, (*allocated - prev) * size);
-
- return q;
-}
-
bool id128_is_valid(const char *s) {
size_t i, l;
@@ -2956,120 +659,6 @@ bool id128_is_valid(const char *s) {
return true;
}
-int shall_restore_state(void) {
- _cleanup_free_ char *value = NULL;
- int r;
-
- r = get_proc_cmdline_key("systemd.restore_state=", &value);
- if (r < 0)
- return r;
- if (r == 0)
- return true;
-
- return parse_boolean(value) != 0;
-}
-
-int proc_cmdline(char **ret) {
- assert(ret);
-
- if (detect_container() > 0)
- return get_process_cmdline(1, 0, false, ret);
- else
- return read_one_line_file("/proc/cmdline", ret);
-}
-
-int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
- _cleanup_free_ char *line = NULL;
- const char *p;
- int r;
-
- assert(parse_item);
-
- r = proc_cmdline(&line);
- if (r < 0)
- return r;
-
- p = line;
- for (;;) {
- _cleanup_free_ char *word = NULL;
- char *value = NULL;
-
- r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- /* Filter out arguments that are intended only for the
- * initrd */
- if (!in_initrd() && startswith(word, "rd."))
- continue;
-
- value = strchr(word, '=');
- if (value)
- *(value++) = 0;
-
- r = parse_item(word, value);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int get_proc_cmdline_key(const char *key, char **value) {
- _cleanup_free_ char *line = NULL, *ret = NULL;
- bool found = false;
- const char *p;
- int r;
-
- assert(key);
-
- r = proc_cmdline(&line);
- if (r < 0)
- return r;
-
- p = line;
- for (;;) {
- _cleanup_free_ char *word = NULL;
- const char *e;
-
- r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- /* Filter out arguments that are intended only for the
- * initrd */
- if (!in_initrd() && startswith(word, "rd."))
- continue;
-
- if (value) {
- e = startswith(word, key);
- if (!e)
- continue;
-
- r = free_and_strdup(&ret, e);
- if (r < 0)
- return r;
-
- found = true;
- } else {
- if (streq(word, key))
- found = true;
- }
- }
-
- if (value) {
- *value = ret;
- ret = NULL;
- }
-
- return found;
-
-}
-
int container_get_leader(const char *machine, pid_t *pid) {
_cleanup_free_ char *s = NULL, *class = NULL;
const char *p;
@@ -3219,136 +808,6 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
return reset_uid_gid();
}
-/* This is much like like mkostemp() but is subject to umask(). */
-int mkostemp_safe(char *pattern, int flags) {
- _cleanup_umask_ mode_t u;
- int fd;
-
- assert(pattern);
-
- u = umask(077);
-
- fd = mkostemp(pattern, flags);
- if (fd < 0)
- return -errno;
-
- return fd;
-}
-
-int open_tmpfile(const char *path, int flags) {
- char *p;
- int fd;
-
- assert(path);
-
-#ifdef O_TMPFILE
- /* Try O_TMPFILE first, if it is supported */
- fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
- if (fd >= 0)
- return fd;
-#endif
-
- /* Fall back to unguessable name + unlinking */
- p = strjoina(path, "/systemd-tmp-XXXXXX");
-
- fd = mkostemp_safe(p, flags);
- if (fd < 0)
- return fd;
-
- unlink(p);
- return fd;
-}
-
-int fd_warn_permissions(const char *path, int fd) {
- struct stat st;
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- if (st.st_mode & 0111)
- log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
-
- if (st.st_mode & 0002)
- log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
-
- if (getpid() == 1 && (st.st_mode & 0044) != 0044)
- log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path);
-
- return 0;
-}
-
-unsigned long personality_from_string(const char *p) {
-
- /* Parse a personality specifier. We introduce our own
- * identifiers that indicate specific ABIs, rather than just
- * hints regarding the register size, since we want to keep
- * things open for multiple locally supported ABIs for the
- * same register size. We try to reuse the ABI identifiers
- * used by libseccomp. */
-
-#if defined(__x86_64__)
-
- if (streq(p, "x86"))
- return PER_LINUX32;
-
- if (streq(p, "x86-64"))
- return PER_LINUX;
-
-#elif defined(__i386__)
-
- if (streq(p, "x86"))
- return PER_LINUX;
-
-#elif defined(__s390x__)
-
- if (streq(p, "s390"))
- return PER_LINUX32;
-
- if (streq(p, "s390x"))
- return PER_LINUX;
-
-#elif defined(__s390__)
-
- if (streq(p, "s390"))
- return PER_LINUX;
-#endif
-
- return PERSONALITY_INVALID;
-}
-
-const char* personality_to_string(unsigned long p) {
-
-#if defined(__x86_64__)
-
- if (p == PER_LINUX32)
- return "x86";
-
- if (p == PER_LINUX)
- return "x86-64";
-
-#elif defined(__i386__)
-
- if (p == PER_LINUX)
- return "x86";
-
-#elif defined(__s390x__)
-
- if (p == PER_LINUX)
- return "s390x";
-
- if (p == PER_LINUX32)
- return "s390";
-
-#elif defined(__s390__)
-
- if (p == PER_LINUX)
- return "s390";
-
-#endif
-
- return NULL;
-}
-
uint64_t physical_memory(void) {
long mem;
@@ -3361,49 +820,6 @@ uint64_t physical_memory(void) {
return (uint64_t) mem * (uint64_t) page_size();
}
-void hexdump(FILE *f, const void *p, size_t s) {
- const uint8_t *b = p;
- unsigned n = 0;
-
- assert(s == 0 || b);
-
- while (s > 0) {
- size_t i;
-
- fprintf(f, "%04x ", n);
-
- for (i = 0; i < 16; i++) {
-
- if (i >= s)
- fputs(" ", f);
- else
- fprintf(f, "%02x ", b[i]);
-
- if (i == 7)
- fputc(' ', f);
- }
-
- fputc(' ', f);
-
- for (i = 0; i < 16; i++) {
-
- if (i >= s)
- fputc(' ', f);
- else
- fputc(isprint(b[i]) ? (char) b[i] : '.', f);
- }
-
- fputc('\n', f);
-
- if (s < 16)
- break;
-
- n += 16;
- b += 16;
- s -= 16;
- }
-}
-
int update_reboot_param_file(const char *param) {
int r = 0;
@@ -3417,846 +833,8 @@ int update_reboot_param_file(const char *param) {
return 0;
}
-int umount_recursive(const char *prefix, int flags) {
- bool again;
- int n = 0, r;
-
- /* Try to umount everything recursively below a
- * directory. Also, take care of stacked mounts, and keep
- * unmounting them until they are gone. */
-
- do {
- _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
-
- again = false;
- r = 0;
-
- proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
- if (!proc_self_mountinfo)
- return -errno;
-
- for (;;) {
- _cleanup_free_ char *path = NULL, *p = NULL;
- int k;
-
- k = fscanf(proc_self_mountinfo,
- "%*s " /* (1) mount id */
- "%*s " /* (2) parent id */
- "%*s " /* (3) major:minor */
- "%*s " /* (4) root */
- "%ms " /* (5) mount point */
- "%*s" /* (6) mount options */
- "%*[^-]" /* (7) optional fields */
- "- " /* (8) separator */
- "%*s " /* (9) file system type */
- "%*s" /* (10) mount source */
- "%*s" /* (11) mount options 2 */
- "%*[^\n]", /* some rubbish at the end */
- &path);
- if (k != 1) {
- if (k == EOF)
- break;
-
- continue;
- }
-
- r = cunescape(path, UNESCAPE_RELAX, &p);
- if (r < 0)
- return r;
-
- if (!path_startswith(p, prefix))
- continue;
-
- if (umount2(p, flags) < 0) {
- r = -errno;
- continue;
- }
-
- again = true;
- n++;
-
- break;
- }
-
- } while (again);
-
- return r ? r : n;
-}
-
-static int get_mount_flags(const char *path, unsigned long *flags) {
- struct statvfs buf;
-
- if (statvfs(path, &buf) < 0)
- return -errno;
- *flags = buf.f_flag;
- return 0;
-}
-
-int bind_remount_recursive(const char *prefix, bool ro) {
- _cleanup_set_free_free_ Set *done = NULL;
- _cleanup_free_ char *cleaned = NULL;
- int r;
-
- /* Recursively remount a directory (and all its submounts)
- * read-only or read-write. If the directory is already
- * mounted, we reuse the mount and simply mark it
- * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
- * operation). If it isn't we first make it one. Afterwards we
- * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all
- * submounts we can access, too. When mounts are stacked on
- * the same mount point we only care for each individual
- * "top-level" mount on each point, as we cannot
- * influence/access the underlying mounts anyway. We do not
- * have any effect on future submounts that might get
- * propagated, they migt be writable. This includes future
- * submounts that have been triggered via autofs. */
-
- cleaned = strdup(prefix);
- if (!cleaned)
- return -ENOMEM;
-
- path_kill_slashes(cleaned);
-
- done = set_new(&string_hash_ops);
- if (!done)
- return -ENOMEM;
-
- for (;;) {
- _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
- _cleanup_set_free_free_ Set *todo = NULL;
- bool top_autofs = false;
- char *x;
- unsigned long orig_flags;
-
- todo = set_new(&string_hash_ops);
- if (!todo)
- return -ENOMEM;
-
- proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
- if (!proc_self_mountinfo)
- return -errno;
-
- for (;;) {
- _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
- int k;
-
- k = fscanf(proc_self_mountinfo,
- "%*s " /* (1) mount id */
- "%*s " /* (2) parent id */
- "%*s " /* (3) major:minor */
- "%*s " /* (4) root */
- "%ms " /* (5) mount point */
- "%*s" /* (6) mount options (superblock) */
- "%*[^-]" /* (7) optional fields */
- "- " /* (8) separator */
- "%ms " /* (9) file system type */
- "%*s" /* (10) mount source */
- "%*s" /* (11) mount options (bind mount) */
- "%*[^\n]", /* some rubbish at the end */
- &path,
- &type);
- if (k != 2) {
- if (k == EOF)
- break;
-
- continue;
- }
-
- r = cunescape(path, UNESCAPE_RELAX, &p);
- if (r < 0)
- return r;
-
- /* Let's ignore autofs mounts. If they aren't
- * triggered yet, we want to avoid triggering
- * them, as we don't make any guarantees for
- * future submounts anyway. If they are
- * already triggered, then we will find
- * another entry for this. */
- if (streq(type, "autofs")) {
- top_autofs = top_autofs || path_equal(cleaned, p);
- continue;
- }
-
- if (path_startswith(p, cleaned) &&
- !set_contains(done, p)) {
-
- r = set_consume(todo, p);
- p = NULL;
-
- if (r == -EEXIST)
- continue;
- if (r < 0)
- return r;
- }
- }
-
- /* If we have no submounts to process anymore and if
- * the root is either already done, or an autofs, we
- * are done */
- if (set_isempty(todo) &&
- (top_autofs || set_contains(done, cleaned)))
- return 0;
-
- if (!set_contains(done, cleaned) &&
- !set_contains(todo, cleaned)) {
- /* The prefix directory itself is not yet a
- * mount, make it one. */
- if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
- return -errno;
-
- orig_flags = 0;
- (void) get_mount_flags(cleaned, &orig_flags);
- orig_flags &= ~MS_RDONLY;
-
- if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
- return -errno;
-
- x = strdup(cleaned);
- if (!x)
- return -ENOMEM;
-
- r = set_consume(done, x);
- if (r < 0)
- return r;
- }
-
- while ((x = set_steal_first(todo))) {
-
- r = set_consume(done, x);
- if (r == -EEXIST || r == 0)
- continue;
- if (r < 0)
- return r;
-
- /* Try to reuse the original flag set, but
- * don't care for errors, in case of
- * obstructed mounts */
- orig_flags = 0;
- (void) get_mount_flags(x, &orig_flags);
- orig_flags &= ~MS_RDONLY;
-
- if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) {
-
- /* Deal with mount points that are
- * obstructed by a later mount */
-
- if (errno != ENOENT)
- return -errno;
- }
-
- }
- }
-}
-
-int fflush_and_check(FILE *f) {
- assert(f);
-
- errno = 0;
- fflush(f);
-
- if (ferror(f))
- return errno ? -errno : -EIO;
-
- return 0;
-}
-
-int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
- const char *fn;
- char *t;
-
- assert(p);
- assert(ret);
-
- /*
- * Turns this:
- * /foo/bar/waldo
- *
- * Into this:
- * /foo/bar/.#<extra>waldoXXXXXX
- */
-
- fn = basename(p);
- if (!filename_is_valid(fn))
- return -EINVAL;
-
- if (extra == NULL)
- extra = "";
-
- t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1);
- if (!t)
- return -ENOMEM;
-
- strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX");
-
- *ret = path_kill_slashes(t);
- return 0;
-}
-
-int tempfn_random(const char *p, const char *extra, char **ret) {
- const char *fn;
- char *t, *x;
- uint64_t u;
- unsigned i;
-
- assert(p);
- assert(ret);
-
- /*
- * Turns this:
- * /foo/bar/waldo
- *
- * Into this:
- * /foo/bar/.#<extra>waldobaa2a261115984a9
- */
-
- fn = basename(p);
- if (!filename_is_valid(fn))
- return -EINVAL;
-
- if (!extra)
- extra = "";
-
- t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1);
- if (!t)
- return -ENOMEM;
-
- x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn);
-
- u = random_u64();
- for (i = 0; i < 16; i++) {
- *(x++) = hexchar(u & 0xF);
- u >>= 4;
- }
-
- *x = 0;
-
- *ret = path_kill_slashes(t);
- return 0;
-}
-
-int tempfn_random_child(const char *p, const char *extra, char **ret) {
- char *t, *x;
- uint64_t u;
- unsigned i;
-
- assert(p);
- assert(ret);
-
- /* Turns this:
- * /foo/bar/waldo
- * Into this:
- * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
- */
-
- if (!extra)
- extra = "";
-
- t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1);
- if (!t)
- return -ENOMEM;
-
- x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
-
- u = random_u64();
- for (i = 0; i < 16; i++) {
- *(x++) = hexchar(u & 0xF);
- u >>= 4;
- }
-
- *x = 0;
-
- *ret = path_kill_slashes(t);
- return 0;
-}
-
-int take_password_lock(const char *root) {
-
- struct flock flock = {
- .l_type = F_WRLCK,
- .l_whence = SEEK_SET,
- .l_start = 0,
- .l_len = 0,
- };
-
- const char *path;
- int fd, r;
-
- /* This is roughly the same as lckpwdf(), but not as awful. We
- * don't want to use alarm() and signals, hence we implement
- * our own trivial version of this.
- *
- * Note that shadow-utils also takes per-database locks in
- * addition to lckpwdf(). However, we don't given that they
- * are redundant as they they invoke lckpwdf() first and keep
- * it during everything they do. The per-database locks are
- * awfully racy, and thus we just won't do them. */
-
- if (root)
- path = strjoina(root, "/etc/.pwd.lock");
- else
- path = "/etc/.pwd.lock";
-
- fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
- if (fd < 0)
- return -errno;
-
- r = fcntl(fd, F_SETLKW, &flock);
- if (r < 0) {
- safe_close(fd);
- return -errno;
- }
-
- return fd;
-}
-
-int is_symlink(const char *path) {
- struct stat info;
-
- if (lstat(path, &info) < 0)
- return -errno;
-
- return !!S_ISLNK(info.st_mode);
-}
-
-int is_dir(const char* path, bool follow) {
- struct stat st;
- int r;
-
- if (follow)
- r = stat(path, &st);
- else
- r = lstat(path, &st);
- if (r < 0)
- return -errno;
-
- return !!S_ISDIR(st.st_mode);
-}
-
-int is_device_node(const char *path) {
- struct stat info;
-
- if (lstat(path, &info) < 0)
- return -errno;
-
- return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
-}
-
-ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) {
- char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
- _cleanup_close_ int fd = -1;
- ssize_t l;
-
- /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
-
- fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
- if (fd < 0)
- return -errno;
-
- xsprintf(fn, "/proc/self/fd/%i", fd);
-
- l = getxattr(fn, attribute, value, size);
- if (l < 0)
- return -errno;
-
- return l;
-}
-
-static int parse_crtime(le64_t le, usec_t *usec) {
- uint64_t u;
-
- assert(usec);
-
- u = le64toh(le);
- if (u == 0 || u == (uint64_t) -1)
- return -EIO;
-
- *usec = (usec_t) u;
- return 0;
-}
-
-int fd_getcrtime(int fd, usec_t *usec) {
- le64_t le;
- ssize_t n;
-
- assert(fd >= 0);
- assert(usec);
-
- /* Until Linux gets a real concept of birthtime/creation time,
- * let's fake one with xattrs */
-
- n = fgetxattr(fd, "user.crtime_usec", &le, sizeof(le));
- if (n < 0)
- return -errno;
- if (n != sizeof(le))
- return -EIO;
-
- return parse_crtime(le, usec);
-}
-
-int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags) {
- le64_t le;
- ssize_t n;
-
- n = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags);
- if (n < 0)
- return -errno;
- if (n != sizeof(le))
- return -EIO;
-
- return parse_crtime(le, usec);
-}
-
-int path_getcrtime(const char *p, usec_t *usec) {
- le64_t le;
- ssize_t n;
-
- assert(p);
- assert(usec);
-
- n = getxattr(p, "user.crtime_usec", &le, sizeof(le));
- if (n < 0)
- return -errno;
- if (n != sizeof(le))
- return -EIO;
-
- return parse_crtime(le, usec);
-}
-
-int fd_setcrtime(int fd, usec_t usec) {
- le64_t le;
-
- assert(fd >= 0);
-
- if (usec <= 0)
- usec = now(CLOCK_REALTIME);
-
- le = htole64((uint64_t) usec);
- if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), 0) < 0)
- return -errno;
-
- return 0;
-}
-
-int chattr_fd(int fd, unsigned value, unsigned mask) {
- unsigned old_attr, new_attr;
- struct stat st;
-
- assert(fd >= 0);
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- /* Explicitly check whether this is a regular file or
- * directory. If it is anything else (such as a device node or
- * fifo), then the ioctl will not hit the file systems but
- * possibly drivers, where the ioctl might have different
- * effects. Notably, DRM is using the same ioctl() number. */
-
- if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
- return -ENOTTY;
-
- if (mask == 0)
- return 0;
-
- if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0)
- return -errno;
-
- new_attr = (old_attr & ~mask) | (value & mask);
- if (new_attr == old_attr)
- return 0;
-
- if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0)
- return -errno;
-
- return 1;
-}
-
-int chattr_path(const char *p, unsigned value, unsigned mask) {
- _cleanup_close_ int fd = -1;
-
- assert(p);
-
- if (mask == 0)
- return 0;
-
- fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- return chattr_fd(fd, value, mask);
-}
-
-int read_attr_fd(int fd, unsigned *ret) {
- struct stat st;
-
- assert(fd >= 0);
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
- return -ENOTTY;
-
- if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0)
- return -errno;
-
- return 0;
-}
-
-int read_attr_path(const char *p, unsigned *ret) {
- _cleanup_close_ int fd = -1;
-
- assert(p);
- assert(ret);
-
- fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- return read_attr_fd(fd, ret);
-}
-
-int syslog_parse_priority(const char **p, int *priority, bool with_facility) {
- int a = 0, b = 0, c = 0;
- int k;
-
- assert(p);
- assert(*p);
- assert(priority);
-
- if ((*p)[0] != '<')
- return 0;
-
- if (!strchr(*p, '>'))
- return 0;
-
- if ((*p)[2] == '>') {
- c = undecchar((*p)[1]);
- k = 3;
- } else if ((*p)[3] == '>') {
- b = undecchar((*p)[1]);
- c = undecchar((*p)[2]);
- k = 4;
- } else if ((*p)[4] == '>') {
- a = undecchar((*p)[1]);
- b = undecchar((*p)[2]);
- c = undecchar((*p)[3]);
- k = 5;
- } else
- return 0;
-
- if (a < 0 || b < 0 || c < 0 ||
- (!with_facility && (a || b || c > 7)))
- return 0;
-
- if (with_facility)
- *priority = a*100 + b*10 + c;
- else
- *priority = (*priority & LOG_FACMASK) | c;
-
- *p += k;
- return 1;
-}
-
-ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
- size_t i;
-
- if (!key)
- return -1;
-
- for (i = 0; i < len; ++i)
- if (streq_ptr(table[i], key))
- return (ssize_t) i;
-
- return -1;
-}
-
-int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
- struct stat buf;
- int ret;
-
- ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
- if (ret >= 0)
- return 0;
-
- /* renameat2() exists since Linux 3.15, btrfs added support for it later.
- * If it is not implemented, fallback to another method. */
- if (!IN_SET(errno, EINVAL, ENOSYS))
- return -errno;
-
- /* The link()/unlink() fallback does not work on directories. But
- * renameat() without RENAME_NOREPLACE gives the same semantics on
- * directories, except when newpath is an *empty* directory. This is
- * good enough. */
- ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
- if (ret >= 0 && S_ISDIR(buf.st_mode)) {
- ret = renameat(olddirfd, oldpath, newdirfd, newpath);
- return ret >= 0 ? 0 : -errno;
- }
-
- /* If it is not a directory, use the link()/unlink() fallback. */
- ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
- if (ret < 0)
- return -errno;
-
- ret = unlinkat(olddirfd, oldpath, 0);
- if (ret < 0) {
- /* backup errno before the following unlinkat() alters it */
- ret = errno;
- (void) unlinkat(newdirfd, newpath, 0);
- errno = ret;
- return -errno;
- }
-
- return 0;
-}
-
-int parse_mode(const char *s, mode_t *ret) {
- char *x;
- long l;
-
- assert(s);
- assert(ret);
-
- errno = 0;
- l = strtol(s, &x, 8);
- if (errno != 0)
- return -errno;
-
- if (!x || x == s || *x)
- return -EINVAL;
- if (l < 0 || l > 07777)
- return -ERANGE;
-
- *ret = (mode_t) l;
- return 0;
-}
-
-int mount_move_root(const char *path) {
- assert(path);
-
- if (chdir(path) < 0)
- return -errno;
-
- if (mount(path, "/", NULL, MS_MOVE, NULL) < 0)
- return -errno;
-
- if (chroot(".") < 0)
- return -errno;
-
- if (chdir("/") < 0)
- return -errno;
-
- return 0;
-}
-
-int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) {
- char *v;
- size_t l;
- ssize_t n;
-
- assert(path);
- assert(name);
- assert(value);
-
- for (l = 100; ; l = (size_t) n + 1) {
- v = new0(char, l);
- if (!v)
- return -ENOMEM;
-
- if (allow_symlink)
- n = lgetxattr(path, name, v, l);
- else
- n = getxattr(path, name, v, l);
-
- if (n >= 0 && (size_t) n < l) {
- *value = v;
- return n;
- }
-
- free(v);
-
- if (n < 0 && errno != ERANGE)
- return -errno;
-
- if (allow_symlink)
- n = lgetxattr(path, name, NULL, 0);
- else
- n = getxattr(path, name, NULL, 0);
- if (n < 0)
- return -errno;
- }
-}
-
-int fgetxattr_malloc(int fd, const char *name, char **value) {
- char *v;
- size_t l;
- ssize_t n;
-
- assert(fd >= 0);
- assert(name);
- assert(value);
-
- for (l = 100; ; l = (size_t) n + 1) {
- v = new0(char, l);
- if (!v)
- return -ENOMEM;
-
- n = fgetxattr(fd, name, v, l);
-
- if (n >= 0 && (size_t) n < l) {
- *value = v;
- return n;
- }
-
- free(v);
-
- if (n < 0 && errno != ERANGE)
- return -errno;
-
- n = fgetxattr(fd, name, NULL, 0);
- if (n < 0)
- return -errno;
- }
-}
-
-void nop_signal_handler(int sig) {
- /* nothing here */
-}
-
int version(void) {
puts(PACKAGE_STRING "\n"
SYSTEMD_FEATURES);
return 0;
}
-
-bool fdname_is_valid(const char *s) {
- const char *p;
-
- /* Validates a name for $LISTEN_FDNAMES. We basically allow
- * everything ASCII that's not a control character. Also, as
- * special exception the ":" character is not allowed, as we
- * use that as field separator in $LISTEN_FDNAMES.
- *
- * Note that the empty string is explicitly allowed
- * here. However, we limit the length of the names to 255
- * characters. */
-
- if (!s)
- return false;
-
- for (p = s; *p; p++) {
- if (*p < ' ')
- return false;
- if (*p >= 127)
- return false;
- if (*p == ':')
- return false;
- }
-
- return p - s < 256;
-}
-
-bool oom_score_adjust_is_valid(int oa) {
- return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
-}
diff --git a/src/basic/util.h b/src/basic/util.h
index f32033767a..a8fba372d1 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -22,12 +22,10 @@
***/
#include <alloca.h>
-#include <dirent.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <locale.h>
-#include <mntent.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
@@ -53,28 +51,9 @@
#define COMMENTS "#;"
#define GLOB_CHARS "*?["
-#define FORMAT_BYTES_MAX 8
-
size_t page_size(void) _pure_;
#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
-#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n)))
-
-#define new0(t, n) ((t*) calloc((n), sizeof(t)))
-
-#define newa(t, n) ((t*) alloca(sizeof(t)*(n)))
-
-#define newa0(t, n) ((t*) alloca0(sizeof(t)*(n)))
-
-#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
-
-#define malloc0(n) (calloc(1, (n)))
-
-static inline void *mfree(void *memory) {
- free(memory);
- return NULL;
-}
-
static inline const char* yes_no(bool b) {
return b ? "yes" : "no";
}
@@ -87,220 +66,13 @@ static inline const char* one_zero(bool b) {
return b ? "1" : "0";
}
-int parse_size(const char *t, uint64_t base, uint64_t *size);
-
-int parse_boolean(const char *v) _pure_;
-int parse_pid(const char *s, pid_t* ret_pid);
-
-int safe_atou(const char *s, unsigned *ret_u);
-int safe_atoi(const char *s, int *ret_i);
-
-int safe_atollu(const char *s, unsigned long long *ret_u);
-int safe_atolli(const char *s, long long int *ret_i);
-
-int safe_atod(const char *s, double *ret_d);
-
-int safe_atou8(const char *s, uint8_t *ret);
-
-#if LONG_MAX == INT_MAX
-static inline int safe_atolu(const char *s, unsigned long *ret_u) {
- assert_cc(sizeof(unsigned long) == sizeof(unsigned));
- return safe_atou(s, (unsigned*) ret_u);
-}
-static inline int safe_atoli(const char *s, long int *ret_u) {
- assert_cc(sizeof(long int) == sizeof(int));
- return safe_atoi(s, (int*) ret_u);
-}
-#else
-static inline int safe_atolu(const char *s, unsigned long *ret_u) {
- assert_cc(sizeof(unsigned long) == sizeof(unsigned long long));
- return safe_atollu(s, (unsigned long long*) ret_u);
-}
-static inline int safe_atoli(const char *s, long int *ret_u) {
- assert_cc(sizeof(long int) == sizeof(long long int));
- return safe_atolli(s, (long long int*) ret_u);
-}
-#endif
-
-static inline int safe_atou32(const char *s, uint32_t *ret_u) {
- assert_cc(sizeof(uint32_t) == sizeof(unsigned));
- return safe_atou(s, (unsigned*) ret_u);
-}
-
-static inline int safe_atoi32(const char *s, int32_t *ret_i) {
- assert_cc(sizeof(int32_t) == sizeof(int));
- return safe_atoi(s, (int*) ret_i);
-}
-
-static inline int safe_atou64(const char *s, uint64_t *ret_u) {
- assert_cc(sizeof(uint64_t) == sizeof(unsigned long long));
- return safe_atollu(s, (unsigned long long*) ret_u);
-}
-
-static inline int safe_atoi64(const char *s, int64_t *ret_i) {
- assert_cc(sizeof(int64_t) == sizeof(long long int));
- return safe_atolli(s, (long long int*) ret_i);
-}
-
-int safe_atou16(const char *s, uint16_t *ret);
-int safe_atoi16(const char *s, int16_t *ret);
-
-int readlinkat_malloc(int fd, const char *p, char **ret);
-int readlink_malloc(const char *p, char **r);
-int readlink_value(const char *p, char **ret);
-int readlink_and_make_absolute(const char *p, char **r);
-int readlink_and_canonicalize(const char *p, char **r);
-
-char *file_in_same_dir(const char *path, const char *filename);
-
-int rmdir_parents(const char *path, const char *stop);
-
-char hexchar(int x) _const_;
-int unhexchar(char c) _const_;
-char octchar(int x) _const_;
-int unoctchar(char c) _const_;
-char decchar(int x) _const_;
-int undecchar(char c) _const_;
-char base32hexchar(int x) _const_;
-int unbase32hexchar(char c) _const_;
-char base64char(int x) _const_;
-int unbase64char(char c) _const_;
-
-bool dirent_is_file(const struct dirent *de) _pure_;
-bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;
-
-bool hidden_file(const char *filename) _pure_;
-
-/* For basic lookup tables with strictly enumerated entries */
-#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
- scope const char *name##_to_string(type i) { \
- if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \
- return NULL; \
- return name##_table[i]; \
- }
-
-ssize_t string_table_lookup(const char * const *table, size_t len, const char *key);
-
-#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
- scope type name##_from_string(const char *s) { \
- return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
- }
-
-#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
- _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
- struct __useless_struct_to_allow_trailing_semicolon__
-
-#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
-
-/* For string conversions where numbers are also acceptable */
-#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \
- int name##_to_string_alloc(type i, char **str) { \
- char *s; \
- if (i < 0 || i > max) \
- return -ERANGE; \
- if (i < (type) ELEMENTSOF(name##_table)) { \
- s = strdup(name##_table[i]); \
- if (!s) \
- return -ENOMEM; \
- } else { \
- if (asprintf(&s, "%i", i) < 0) \
- return -ENOMEM; \
- } \
- *str = s; \
- return 0; \
- } \
- type name##_from_string(const char *s) { \
- type i; \
- unsigned u = 0; \
- if (!s) \
- return (type) -1; \
- for (i = 0; i < (type) ELEMENTSOF(name##_table); i++) \
- if (streq_ptr(name##_table[i], s)) \
- return i; \
- if (safe_atou(s, &u) >= 0 && u <= max) \
- return (type) u; \
- return (type) -1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
-
-bool fstype_is_network(const char *fstype);
-
-int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
-
-bool is_device_path(const char *path);
-
-int dir_is_empty(const char *path);
-char* dirname_malloc(const char *path);
-
-static inline int dir_is_populated(const char *path) {
- int r;
- r = dir_is_empty(path);
- if (r < 0)
- return r;
- return !r;
-}
-
-int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
-
-typedef long statfs_f_type_t;
-
-bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_;
-int fd_check_fstype(int fd, statfs_f_type_t magic_value);
-int path_check_fstype(const char *path, statfs_f_type_t magic_value);
-
-bool is_temporary_fs(const struct statfs *s) _pure_;
-int fd_is_temporary_fs(int fd);
-
-#define xsprintf(buf, fmt, ...) \
- assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), \
- "xsprintf: " #buf "[] must be big enough")
-
-int files_same(const char *filea, const char *fileb);
-
-int running_in_chroot(void);
-
-int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode);
-int touch(const char *path);
-
-noreturn void freeze(void);
-
-bool null_or_empty(struct stat *st) _pure_;
-int null_or_empty_path(const char *fn);
-int null_or_empty_fd(int fd);
-
-DIR *xopendirat(int dirfd, const char *name, int flags);
-
-char *fstab_node_to_udev_node(const char *p);
-
void execute_directories(const char* const* directories, usec_t timeout, char *argv[]);
bool plymouth_running(void);
-int symlink_idempotent(const char *from, const char *to);
-
-int symlink_atomic(const char *from, const char *to);
-int mknod_atomic(const char *path, mode_t mode, dev_t dev);
-int mkfifo_atomic(const char *path, mode_t mode);
-
-int fchmod_umask(int fd, mode_t mode);
-
bool display_is_local(const char *display) _pure_;
int socket_from_display(const char *display, char **path);
-int glob_exists(const char *path);
-int glob_extend(char ***strv, const char *path);
-
-int dirent_ensure_type(DIR *d, struct dirent *de);
-
-int get_files_in_directory(const char *path, char ***list);
-
-bool is_main_thread(void);
-
int block_get_whole_disk(dev_t d, dev_t *ret);
#define NULSTR_FOREACH(i, l) \
@@ -309,26 +81,6 @@ int block_get_whole_disk(dev_t d, dev_t *ret);
#define NULSTR_FOREACH_PAIR(i, j, l) \
for ((i) = (l), (j) = strchr((i), 0)+1; (i) && *(i); (i) = strchr((j), 0)+1, (j) = *(i) ? strchr((i), 0)+1 : (i))
-int ioprio_class_to_string_alloc(int i, char **s);
-int ioprio_class_from_string(const char *s);
-
-const char *sigchld_code_to_string(int i) _const_;
-int sigchld_code_from_string(const char *s) _pure_;
-
-int log_facility_unshifted_to_string_alloc(int i, char **s);
-int log_facility_unshifted_from_string(const char *s);
-bool log_facility_unshifted_is_valid(int faciliy);
-
-int log_level_to_string_alloc(int i, char **s);
-int log_level_from_string(const char *s);
-bool log_level_is_valid(int level);
-
-int sched_policy_to_string_alloc(int i, char **s);
-int sched_policy_from_string(const char *s);
-
-const char *rlimit_to_string(int i) _const_;
-int rlimit_from_string(const char *s) _pure_;
-
extern int saved_argc;
extern char **saved_argv;
@@ -336,147 +88,36 @@ bool kexec_loaded(void);
int prot_from_flags(int flags) _const_;
-char *format_bytes(char *buf, size_t l, uint64_t t);
-
-void* memdup(const void *p, size_t l) _alloc_(2);
-
int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
-int setrlimit_closest(int resource, const struct rlimit *rlim);
-
-bool http_url_is_valid(const char *url) _pure_;
-bool documentation_url_is_valid(const char *url) _pure_;
-
-bool http_etag_is_valid(const char *etag);
-
bool in_initrd(void);
-static inline void freep(void *p) {
- free(*(void**) p);
-}
-
-static inline void umaskp(mode_t *u) {
- umask(*u);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
-
-#define _cleanup_free_ _cleanup_(freep)
-#define _cleanup_umask_ _cleanup_(umaskp)
-#define _cleanup_globfree_ _cleanup_(globfree)
-#define _cleanup_endmntent_ _cleanup_(endmntentp)
-
-_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) {
- if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
- return NULL;
-
- return malloc(a * b);
-}
-
-_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) {
- if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
- return NULL;
-
- return realloc(p, a * b);
-}
-
-_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) {
- if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
- return NULL;
-
- return memdup(p, a * b);
-}
-
-bool filename_is_valid(const char *p) _pure_;
-bool path_is_safe(const char *p) _pure_;
-bool string_is_safe(const char *p) _pure_;
-
-/**
- * Check if a string contains any glob patterns.
- */
-_pure_ static inline bool string_is_glob(const char *p) {
- return !!strpbrk(p, GLOB_CHARS);
-}
-
void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
int (*compar) (const void *, const void *, void *),
void *arg);
-#define _(String) gettext (String)
-#define N_(String) String
-void init_gettext(void);
-bool is_locale_utf8(void);
-
-typedef enum DrawSpecialChar {
- DRAW_TREE_VERTICAL,
- DRAW_TREE_BRANCH,
- DRAW_TREE_RIGHT,
- DRAW_TREE_SPACE,
- DRAW_TRIANGULAR_BULLET,
- DRAW_BLACK_CIRCLE,
- DRAW_ARROW,
- DRAW_DASH,
- _DRAW_SPECIAL_CHAR_MAX
-} DrawSpecialChar;
-
-const char *draw_special_char(DrawSpecialChar ch);
+/**
+ * Normal qsort requires base to be nonnull. Here were require
+ * that only if nmemb > 0.
+ */
+static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) {
+ if (nmemb <= 1)
+ return;
+
+ assert(base);
+ qsort(base, nmemb, size, compar);
+}
int on_ac_power(void);
-int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
-int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
-
-#define FOREACH_LINE(line, f, on_error) \
- for (;;) \
- if (!fgets(line, sizeof(line), f)) { \
- if (ferror(f)) { \
- on_error; \
- } \
- break; \
- } else
-
-#define FOREACH_DIRENT(de, d, on_error) \
- for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \
- if (!de) { \
- if (errno > 0) { \
- on_error; \
- } \
- break; \
- } else if (hidden_file((de)->d_name)) \
- continue; \
- else
-
-#define FOREACH_DIRENT_ALL(de, d, on_error) \
- for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \
- if (!de) { \
- if (errno > 0) { \
- on_error; \
- } \
- break; \
- } else
+#define memzero(x,l) (memset((x), 0, (l)))
+#define zero(x) (memzero(&(x), sizeof(x)))
static inline void *mempset(void *s, int c, size_t n) {
memset(s, c, n);
return (uint8_t*)s + n;
}
-char *hexmem(const void *p, size_t l);
-int unhexmem(const char *p, size_t l, void **mem, size_t *len);
-
-char *base32hexmem(const void *p, size_t l, bool padding);
-int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len);
-
-char *base64mem(const void *p, size_t l);
-int unbase64mem(const char *p, size_t l, void **mem, size_t *len);
-
-void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
-void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
-#define GREEDY_REALLOC(array, allocated, need) \
- greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0]))
-
-#define GREEDY_REALLOC0(array, allocated, need) \
- greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0]))
-
static inline void _reset_errno_(int *saved_errno) {
errno = *saved_errno;
}
@@ -492,20 +133,6 @@ static inline int negative_errno(void) {
return -errno;
}
-struct _umask_struct_ {
- mode_t mask;
- bool quit;
-};
-
-static inline void _reset_umask_(struct _umask_struct_ *s) {
- umask(s->mask);
-};
-
-#define RUN_WITH_UMASK(mask) \
- for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \
- !_saved_umask_.quit ; \
- _saved_umask_.quit = true)
-
static inline unsigned u64log2(uint64_t n) {
#if __SIZEOF_LONG_LONG__ == 8
return (n > 1) ? (unsigned) __builtin_clzll(n) ^ 63U : 0;
@@ -543,154 +170,15 @@ static inline unsigned log2u_round_up(unsigned x) {
return log2u(x - 1) + 1;
}
-#define DECIMAL_STR_WIDTH(x) \
- ({ \
- typeof(x) _x_ = (x); \
- unsigned ans = 1; \
- while (_x_ /= 10) \
- ans++; \
- ans; \
- })
-
-int unlink_noerrno(const char *path);
-
-#define alloca0(n) \
- ({ \
- char *_new_; \
- size_t _len_ = n; \
- _new_ = alloca(_len_); \
- (void *) memset(_new_, 0, _len_); \
- })
-
-/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */
-#define alloca_align(size, align) \
- ({ \
- void *_ptr_; \
- size_t _mask_ = (align) - 1; \
- _ptr_ = alloca((size) + _mask_); \
- (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
- })
-
-#define alloca0_align(size, align) \
- ({ \
- void *_new_; \
- size_t _size_ = (size); \
- _new_ = alloca_align(_size_, (align)); \
- (void*)memset(_new_, 0, _size_); \
- })
-
bool id128_is_valid(const char *s) _pure_;
-int shall_restore_state(void);
-
-/**
- * Normal qsort requires base to be nonnull. Here were require
- * that only if nmemb > 0.
- */
-static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) {
- if (nmemb <= 1)
- return;
-
- assert(base);
- qsort(base, nmemb, size, compar);
-}
-
-int proc_cmdline(char **ret);
-int parse_proc_cmdline(int (*parse_word)(const char *key, const char *value));
-int get_proc_cmdline_key(const char *parameter, char **value);
-
int container_get_leader(const char *machine, pid_t *pid);
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
-int mkostemp_safe(char *pattern, int flags);
-int open_tmpfile(const char *path, int flags);
-
-int fd_warn_permissions(const char *path, int fd);
-
-#ifndef PERSONALITY_INVALID
-/* personality(7) documents that 0xffffffffUL is used for querying the
- * current personality, hence let's use that here as error
- * indicator. */
-#define PERSONALITY_INVALID 0xffffffffLU
-#endif
-
-unsigned long personality_from_string(const char *p);
-const char *personality_to_string(unsigned long);
-
uint64_t physical_memory(void);
-void hexdump(FILE *f, const void *p, size_t s);
-
-union file_handle_union {
- struct file_handle handle;
- char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ];
-};
-#define FILE_HANDLE_INIT { .handle.handle_bytes = MAX_HANDLE_SZ }
-
int update_reboot_param_file(const char *param);
-int umount_recursive(const char *target, int flags);
-
-int bind_remount_recursive(const char *prefix, bool ro);
-
-int fflush_and_check(FILE *f);
-
-int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
-int tempfn_random(const char *p, const char *extra, char **ret);
-int tempfn_random_child(const char *p, const char *extra, char **ret);
-
-int take_password_lock(const char *root);
-
-int is_symlink(const char *path);
-int is_dir(const char *path, bool follow);
-int is_device_node(const char *path);
-
-#define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
-
-#define FOREACH_INOTIFY_EVENT(e, buffer, sz) \
- for ((e) = &buffer.ev; \
- (uint8_t*) (e) < (uint8_t*) (buffer.raw) + (sz); \
- (e) = (struct inotify_event*) ((uint8_t*) (e) + sizeof(struct inotify_event) + (e)->len))
-
-union inotify_event_buffer {
- struct inotify_event ev;
- uint8_t raw[INOTIFY_EVENT_MAX];
-};
-
-#define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW)
-
-ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags);
-
-int fd_setcrtime(int fd, usec_t usec);
-int fd_getcrtime(int fd, usec_t *usec);
-int path_getcrtime(const char *p, usec_t *usec);
-int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags);
-
-int chattr_fd(int fd, unsigned value, unsigned mask);
-int chattr_path(const char *p, unsigned value, unsigned mask);
-
-int read_attr_fd(int fd, unsigned *ret);
-int read_attr_path(const char *p, unsigned *ret);
-
-#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim })
-
-int syslog_parse_priority(const char **p, int *priority, bool with_facility);
-
-int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
-
-int parse_mode(const char *s, mode_t *ret);
-
-int mount_move_root(const char *path);
-
-int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink);
-int fgetxattr_malloc(int fd, const char *name, char **value);
-
-void nop_signal_handler(int sig);
-
int version(void);
-
-bool fdname_is_valid(const char *s);
-
-bool oom_score_adjust_is_valid(int oa);
diff --git a/src/basic/virt.c b/src/basic/virt.c
index 9267a2730b..fb181e5b55 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -23,8 +23,11 @@
#include <string.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fileio.h"
#include "process-util.h"
+#include "stat-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "util.h"
#include "virt.h"
@@ -411,6 +414,16 @@ int detect_virtualization(void) {
return detect_vm();
}
+int running_in_chroot(void) {
+ int ret;
+
+ ret = files_same("/proc/1/root", "/");
+ if (ret < 0)
+ return ret;
+
+ return ret == 0;
+}
+
static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
[VIRTUALIZATION_NONE] = "none",
[VIRTUALIZATION_KVM] = "kvm",
diff --git a/src/basic/virt.h b/src/basic/virt.h
index 449e069901..ed83608019 100644
--- a/src/basic/virt.h
+++ b/src/basic/virt.h
@@ -67,5 +67,7 @@ int detect_vm(void);
int detect_container(void);
int detect_virtualization(void);
+int running_in_chroot(void);
+
const char *virtualization_to_string(int v) _const_;
int virtualization_from_string(const char *s) _pure_;
diff --git a/src/basic/web-util.c b/src/basic/web-util.c
new file mode 100644
index 0000000000..68ec04021b
--- /dev/null
+++ b/src/basic/web-util.c
@@ -0,0 +1,78 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+
+#include "string-util.h"
+#include "utf8.h"
+#include "web-util.h"
+
+bool http_etag_is_valid(const char *etag) {
+ if (isempty(etag))
+ return false;
+
+ if (!endswith(etag, "\""))
+ return false;
+
+ if (!startswith(etag, "\"") && !startswith(etag, "W/\""))
+ return false;
+
+ return true;
+}
+
+bool http_url_is_valid(const char *url) {
+ const char *p;
+
+ if (isempty(url))
+ return false;
+
+ p = startswith(url, "http://");
+ if (!p)
+ p = startswith(url, "https://");
+ if (!p)
+ return false;
+
+ if (isempty(p))
+ return false;
+
+ return ascii_is_valid(p);
+}
+
+bool documentation_url_is_valid(const char *url) {
+ const char *p;
+
+ if (isempty(url))
+ return false;
+
+ if (http_url_is_valid(url))
+ return true;
+
+ p = startswith(url, "file:/");
+ if (!p)
+ p = startswith(url, "info:");
+ if (!p)
+ p = startswith(url, "man:");
+
+ if (isempty(p))
+ return false;
+
+ return ascii_is_valid(p);
+}
diff --git a/src/basic/web-util.h b/src/basic/web-util.h
new file mode 100644
index 0000000000..40c1509eb8
--- /dev/null
+++ b/src/basic/web-util.h
@@ -0,0 +1,32 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+
+#include "macro.h"
+
+bool http_url_is_valid(const char *url) _pure_;
+
+bool documentation_url_is_valid(const char *url) _pure_;
+
+bool http_etag_is_valid(const char *etag);
diff --git a/src/basic/xattr-util.c b/src/basic/xattr-util.c
new file mode 100644
index 0000000000..6abdaedc3e
--- /dev/null
+++ b/src/basic/xattr-util.c
@@ -0,0 +1,195 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/xattr.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "sparse-endian.h"
+#include "stdio-util.h"
+#include "util.h"
+#include "xattr-util.h"
+
+int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) {
+ char *v;
+ size_t l;
+ ssize_t n;
+
+ assert(path);
+ assert(name);
+ assert(value);
+
+ for (l = 100; ; l = (size_t) n + 1) {
+ v = new0(char, l);
+ if (!v)
+ return -ENOMEM;
+
+ if (allow_symlink)
+ n = lgetxattr(path, name, v, l);
+ else
+ n = getxattr(path, name, v, l);
+
+ if (n >= 0 && (size_t) n < l) {
+ *value = v;
+ return n;
+ }
+
+ free(v);
+
+ if (n < 0 && errno != ERANGE)
+ return -errno;
+
+ if (allow_symlink)
+ n = lgetxattr(path, name, NULL, 0);
+ else
+ n = getxattr(path, name, NULL, 0);
+ if (n < 0)
+ return -errno;
+ }
+}
+
+int fgetxattr_malloc(int fd, const char *name, char **value) {
+ char *v;
+ size_t l;
+ ssize_t n;
+
+ assert(fd >= 0);
+ assert(name);
+ assert(value);
+
+ for (l = 100; ; l = (size_t) n + 1) {
+ v = new0(char, l);
+ if (!v)
+ return -ENOMEM;
+
+ n = fgetxattr(fd, name, v, l);
+
+ if (n >= 0 && (size_t) n < l) {
+ *value = v;
+ return n;
+ }
+
+ free(v);
+
+ if (n < 0 && errno != ERANGE)
+ return -errno;
+
+ n = fgetxattr(fd, name, NULL, 0);
+ if (n < 0)
+ return -errno;
+ }
+}
+
+ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) {
+ char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
+ _cleanup_close_ int fd = -1;
+ ssize_t l;
+
+ /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
+
+ fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
+ if (fd < 0)
+ return -errno;
+
+ xsprintf(fn, "/proc/self/fd/%i", fd);
+
+ l = getxattr(fn, attribute, value, size);
+ if (l < 0)
+ return -errno;
+
+ return l;
+}
+
+static int parse_crtime(le64_t le, usec_t *usec) {
+ uint64_t u;
+
+ assert(usec);
+
+ u = le64toh(le);
+ if (u == 0 || u == (uint64_t) -1)
+ return -EIO;
+
+ *usec = (usec_t) u;
+ return 0;
+}
+
+int fd_getcrtime(int fd, usec_t *usec) {
+ le64_t le;
+ ssize_t n;
+
+ assert(fd >= 0);
+ assert(usec);
+
+ /* Until Linux gets a real concept of birthtime/creation time,
+ * let's fake one with xattrs */
+
+ n = fgetxattr(fd, "user.crtime_usec", &le, sizeof(le));
+ if (n < 0)
+ return -errno;
+ if (n != sizeof(le))
+ return -EIO;
+
+ return parse_crtime(le, usec);
+}
+
+int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags) {
+ le64_t le;
+ ssize_t n;
+
+ n = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags);
+ if (n < 0)
+ return -errno;
+ if (n != sizeof(le))
+ return -EIO;
+
+ return parse_crtime(le, usec);
+}
+
+int path_getcrtime(const char *p, usec_t *usec) {
+ le64_t le;
+ ssize_t n;
+
+ assert(p);
+ assert(usec);
+
+ n = getxattr(p, "user.crtime_usec", &le, sizeof(le));
+ if (n < 0)
+ return -errno;
+ if (n != sizeof(le))
+ return -EIO;
+
+ return parse_crtime(le, usec);
+}
+
+int fd_setcrtime(int fd, usec_t usec) {
+ le64_t le;
+
+ assert(fd >= 0);
+
+ if (usec <= 0)
+ usec = now(CLOCK_REALTIME);
+
+ le = htole64((uint64_t) usec);
+ if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), 0) < 0)
+ return -errno;
+
+ return 0;
+}
diff --git a/src/basic/xattr-util.h b/src/basic/xattr-util.h
new file mode 100644
index 0000000000..cf4cb12a25
--- /dev/null
+++ b/src/basic/xattr-util.h
@@ -0,0 +1,38 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "time-util.h"
+
+int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink);
+int fgetxattr_malloc(int fd, const char *name, char **value);
+
+ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags);
+
+int fd_setcrtime(int fd, usec_t usec);
+
+int fd_getcrtime(int fd, usec_t *usec);
+int path_getcrtime(const char *p, usec_t *usec);
+int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags);
diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c
index b96695c353..8e63153c92 100644
--- a/src/binfmt/binfmt.c
+++ b/src/binfmt/binfmt.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
+#include "alloc-util.h"
#include "conf-files.h"
#include "fd-util.h"
#include "fileio.h"
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index a167f8086c..4cf42d17f3 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -37,9 +37,12 @@
#include <sys/statfs.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "blkid-util.h"
#include "efivars.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "locale-util.h"
#include "rm-rf.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c
index ef113ed40c..6723fa5098 100644
--- a/src/bootchart/bootchart.c
+++ b/src/bootchart/bootchart.c
@@ -48,6 +48,7 @@
#include "sd-journal.h"
+#include "alloc-util.h"
#include "bootchart.h"
#include "conf-parser.h"
#include "fd-util.h"
@@ -55,6 +56,7 @@
#include "io-util.h"
#include "list.h"
#include "macro.h"
+#include "parse-util.h"
#include "path-util.h"
#include "store.h"
#include "string-util.h"
diff --git a/src/bootchart/store.c b/src/bootchart/store.c
index 6066e14288..c1b1e77e44 100644
--- a/src/bootchart/store.c
+++ b/src/bootchart/store.c
@@ -31,10 +31,13 @@
#include <time.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "bootchart.h"
#include "cgroup-util.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "parse-util.h"
#include "store.h"
#include "string-util.h"
#include "strxcpyx.h"
diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c
index 43eca90618..05330c0577 100644
--- a/src/bootchart/svg.c
+++ b/src/bootchart/svg.c
@@ -30,6 +30,7 @@
#include <sys/utsname.h>
#include <fcntl.h>
+#include "alloc-util.h"
#include "architecture.h"
#include "util.h"
#include "fileio.h"
diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c
index 7e7574568c..6a7134644f 100644
--- a/src/bus-proxyd/bus-proxyd.c
+++ b/src/bus-proxyd/bus-proxyd.c
@@ -33,9 +33,10 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-xml-policy.h"
-#include "capability.h"
+#include "capability-util.h"
#include "def.h"
#include "fd-util.h"
#include "formats-util.h"
diff --git a/src/bus-proxyd/bus-xml-policy.c b/src/bus-proxyd/bus-xml-policy.c
index 56dcfeab62..f0834e9525 100644
--- a/src/bus-proxyd/bus-xml-policy.c
+++ b/src/bus-proxyd/bus-xml-policy.c
@@ -21,12 +21,15 @@
#include "sd-login.h"
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-xml-policy.h"
#include "conf-files.h"
#include "fileio.h"
#include "formats-util.h"
+#include "locale-util.h"
#include "set.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
diff --git a/src/bus-proxyd/driver.c b/src/bus-proxyd/driver.c
index 4e859412f8..2e8bd83efd 100644
--- a/src/bus-proxyd/driver.c
+++ b/src/bus-proxyd/driver.c
@@ -27,6 +27,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-util.h"
diff --git a/src/bus-proxyd/proxy.c b/src/bus-proxyd/proxy.c
index ea2a01fdae..db399b24f2 100644
--- a/src/bus-proxyd/proxy.c
+++ b/src/bus-proxyd/proxy.c
@@ -31,6 +31,7 @@
#include "sd-bus.h"
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "bus-control.h"
#include "bus-internal.h"
#include "bus-message.h"
@@ -44,6 +45,7 @@
#include "set.h"
#include "strv.h"
#include "synthesize.h"
+#include "user-util.h"
#include "util.h"
static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
diff --git a/src/bus-proxyd/stdio-bridge.c b/src/bus-proxyd/stdio-bridge.c
index a009ea76c4..6e47884209 100644
--- a/src/bus-proxyd/stdio-bridge.c
+++ b/src/bus-proxyd/stdio-bridge.c
@@ -30,6 +30,7 @@
#include "sd-daemon.h"
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-util.h"
#include "def.h"
diff --git a/src/bus-proxyd/test-bus-xml-policy.c b/src/bus-proxyd/test-bus-xml-policy.c
index cb7ff6b970..1f465edd91 100644
--- a/src/bus-proxyd/test-bus-xml-policy.c
+++ b/src/bus-proxyd/test-bus-xml-policy.c
@@ -25,6 +25,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-xml-policy.h"
#include "log.h"
#include "string-util.h"
diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c
index 41c539a1bc..4e9a76a100 100644
--- a/src/cgls/cgls.c
+++ b/src/cgls/cgls.c
@@ -27,6 +27,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "cgroup-show.h"
diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c
index 3786dae2d9..eea8aea76b 100644
--- a/src/cgtop/cgtop.c
+++ b/src/cgtop/cgtop.c
@@ -30,12 +30,14 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "cgroup-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "hashmap.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "terminal-util.h"
diff --git a/src/core/automount.c b/src/core/automount.c
index d362d6579d..4c229247c5 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -29,6 +29,7 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "async.h"
#include "automount.h"
#include "bus-error.h"
@@ -39,10 +40,14 @@
#include "io-util.h"
#include "label.h"
#include "mkdir.h"
+#include "mount-util.h"
#include "mount.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "special.h"
+#include "stdio-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "unit-name.h"
#include "unit.h"
@@ -84,26 +89,11 @@ static void automount_init(Unit *u) {
UNIT(a)->ignore_on_isolate = true;
}
-static void repeat_unmount(const char *path) {
- assert(path);
-
- for (;;) {
- /* If there are multiple mounts on a mount point, this
- * removes them all */
-
- if (umount2(path, MNT_DETACH) >= 0)
- continue;
-
- if (errno != EINVAL)
- log_error_errno(errno, "Failed to unmount: %m");
-
- break;
- }
-}
-
static int automount_send_ready(Automount *a, Set *tokens, int status);
static void unmount_autofs(Automount *a) {
+ int r;
+
assert(a);
if (a->pipe_fd < 0)
@@ -119,8 +109,11 @@ static void unmount_autofs(Automount *a) {
* around */
if (a->where &&
(UNIT(a)->manager->exit_code != MANAGER_RELOAD &&
- UNIT(a)->manager->exit_code != MANAGER_REEXECUTE))
- repeat_unmount(a->where);
+ UNIT(a)->manager->exit_code != MANAGER_REEXECUTE)) {
+ r = repeat_unmount(a->where, MNT_DETACH);
+ if (r < 0)
+ log_error_errno(r, "Failed to unmount: %m");
+ }
}
static void automount_done(Unit *u) {
@@ -140,13 +133,12 @@ static void automount_done(Unit *u) {
static int automount_add_mount_links(Automount *a) {
_cleanup_free_ char *parent = NULL;
- int r;
assert(a);
- r = path_get_parent(a->where, &parent);
- if (r < 0)
- return r;
+ parent = dirname_malloc(a->where);
+ if (!parent)
+ return -ENOMEM;
return unit_require_mounts_for(UNIT(a), parent);
}
@@ -611,12 +603,16 @@ static void automount_enter_waiting(Automount *a) {
return;
fail:
+ log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m");
+
safe_close_pair(p);
- if (mounted)
- repeat_unmount(a->where);
+ if (mounted) {
+ r = repeat_unmount(a->where, MNT_DETACH);
+ if (r < 0)
+ log_error_errno(r, "Failed to unmount, ignoring: %m");
+ }
- log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m");
automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
}
diff --git a/src/core/bus-endpoint.c b/src/core/bus-endpoint.c
index 0c4b3e7c8b..d22a80c91f 100644
--- a/src/core/bus-endpoint.c
+++ b/src/core/bus-endpoint.c
@@ -19,10 +19,11 @@
#include <stdlib.h>
-#include "kdbus.h"
+#include "alloc-util.h"
+#include "bus-endpoint.h"
#include "bus-kernel.h"
#include "bus-policy.h"
-#include "bus-endpoint.h"
+#include "kdbus.h"
int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep) {
diff --git a/src/core/bus-policy.c b/src/core/bus-policy.c
index 2490903a8c..4907c268e8 100644
--- a/src/core/bus-policy.c
+++ b/src/core/bus-policy.c
@@ -19,9 +19,11 @@
#include <stdlib.h>
+#include "alloc-util.h"
#include "bus-kernel.h"
#include "bus-policy.h"
#include "kdbus.h"
+#include "string-table.h"
#include "user-util.h"
#include "util.h"
diff --git a/src/core/busname.c b/src/core/busname.c
index 335a1fdc4c..68508e20d2 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -21,6 +21,7 @@
#include <sys/mman.h>
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-kernel.h"
#include "bus-policy.h"
@@ -30,9 +31,12 @@
#include "fd-util.h"
#include "formats-util.h"
#include "kdbus.h"
+#include "parse-util.h"
+#include "process-util.h"
#include "service.h"
#include "signal-util.h"
#include "special.h"
+#include "string-table.h"
#include "string-util.h"
static const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
@@ -360,10 +364,9 @@ static int busname_coldplug(Unit *u) {
if (n->deserialized_state == n->state)
return 0;
- if (IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) {
-
- if (n->control_pid <= 0)
- return -EBADMSG;
+ if (n->control_pid > 0 &&
+ pid_is_unwaited(n->control_pid) &&
+ IN_SET(n->deserialized_state, BUSNAME_MAKING, BUSNAME_SIGTERM, BUSNAME_SIGKILL)) {
r = unit_watch_pid(UNIT(n), n->control_pid);
if (r < 0)
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 2a2cf02774..bed01fde21 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -22,12 +22,17 @@
#include <fcntl.h>
#include <fnmatch.h>
+#include "alloc-util.h"
#include "cgroup-util.h"
#include "cgroup.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "special.h"
+#include "string-table.h"
#include "string-util.h"
#define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
@@ -1204,7 +1209,7 @@ int unit_search_main_pid(Unit *u, pid_t *ret) {
continue;
/* Ignore processes that aren't our kids */
- if (get_parent_of_pid(npid, &ppid) >= 0 && ppid != mypid)
+ if (get_process_ppid(npid, &ppid) >= 0 && ppid != mypid)
continue;
if (pid != 0)
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
index 6a43be873a..3fd295baa9 100644
--- a/src/core/dbus-cgroup.c
+++ b/src/core/dbus-cgroup.c
@@ -19,11 +19,13 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "bus-util.h"
#include "cgroup-util.h"
#include "cgroup.h"
#include "dbus-cgroup.h"
#include "fd-util.h"
+#include "fileio.h"
#include "path-util.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 12aeda6f2f..db4206a523 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -26,8 +26,9 @@
#endif
#include "af-list.h"
+#include "alloc-util.h"
#include "bus-util.h"
-#include "capability.h"
+#include "capability-util.h"
#include "dbus-execute.h"
#include "env-util.h"
#include "execute.h"
@@ -36,13 +37,16 @@
#include "ioprio.h"
#include "missing.h"
#include "namespace.h"
+#include "parse-util.h"
#include "path-util.h"
-#include "strv.h"
-#include "utf8.h"
-
+#include "process-util.h"
+#include "rlimit-util.h"
#ifdef HAVE_SECCOMP
#include "seccomp-util.h"
#endif
+#include "strv.h"
+#include "syslog-util.h"
+#include "utf8.h"
BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
@@ -109,7 +113,7 @@ static int property_get_oom_score_adjust(
n = 0;
if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
- safe_atoi(t, &n);
+ safe_atoi32(t, &n);
}
return sd_bus_message_append(reply, "i", n);
diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c
index e95ec5c0cb..8c30d66250 100644
--- a/src/core/dbus-job.c
+++ b/src/core/dbus-job.c
@@ -21,12 +21,13 @@
#include "sd-bus.h"
+#include "alloc-util.h"
+#include "dbus-job.h"
#include "dbus.h"
#include "job.h"
#include "log.h"
#include "selinux-access.h"
#include "string-util.h"
-#include "dbus-job.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState);
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 1ef259ec7a..1f9f25093d 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -23,6 +23,7 @@
#include <sys/prctl.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "architecture.h"
#include "build.h"
#include "bus-common-errors.h"
@@ -35,13 +36,16 @@
#include "dbus.h"
#include "env-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "formats-util.h"
#include "install.h"
#include "log.h"
#include "path-util.h"
#include "selinux-access.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
+#include "syslog-util.h"
#include "virt.h"
#include "watchdog.h"
diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c
index f8fb373bf0..16375b2311 100644
--- a/src/core/dbus-scope.c
+++ b/src/core/dbus-scope.c
@@ -19,17 +19,18 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "selinux-access.h"
-#include "unit.h"
-#include "scope.h"
-#include "dbus.h"
-#include "bus-util.h"
-#include "bus-internal.h"
+#include "alloc-util.h"
#include "bus-common-errors.h"
-#include "dbus-unit.h"
+#include "bus-internal.h"
+#include "bus-util.h"
#include "dbus-cgroup.h"
#include "dbus-kill.h"
#include "dbus-scope.h"
+#include "dbus-unit.h"
+#include "dbus.h"
+#include "scope.h"
+#include "selinux-access.h"
+#include "unit.h"
static int bus_scope_abandon(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Scope *s = userdata;
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index 22b8690c54..c41b3e1723 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "async.h"
#include "bus-util.h"
#include "dbus-cgroup.h"
@@ -26,6 +27,7 @@
#include "dbus-kill.h"
#include "dbus-service.h"
#include "fd-util.h"
+#include "fileio.h"
#include "path-util.h"
#include "service.h"
#include "string-util.h"
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
index 5941b72bc0..be5ef261a6 100644
--- a/src/core/dbus-socket.c
+++ b/src/core/dbus-socket.c
@@ -19,13 +19,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "bus-util.h"
#include "dbus-cgroup.h"
#include "dbus-execute.h"
+#include "dbus-socket.h"
#include "socket.h"
#include "string-util.h"
#include "unit.h"
-#include "dbus-socket.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, socket_result, SocketResult);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
index 8ea2cf84a4..a8a280d961 100644
--- a/src/core/dbus-timer.c
+++ b/src/core/dbus-timer.c
@@ -19,11 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "unit.h"
-#include "timer.h"
-#include "dbus-timer.h"
+#include "alloc-util.h"
#include "bus-util.h"
+#include "dbus-timer.h"
#include "strv.h"
+#include "timer.h"
+#include "unit.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult);
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 7220fe688f..6320cd1aa9 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -21,15 +21,18 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "cgroup-util.h"
+#include "dbus-unit.h"
#include "dbus.h"
+#include "locale-util.h"
#include "log.h"
#include "selinux-access.h"
#include "special.h"
#include "string-util.h"
#include "strv.h"
-#include "dbus-unit.h"
+#include "user-util.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 37410a9870..6c44b28adf 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -25,6 +25,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-internal.h"
@@ -45,6 +46,7 @@
#include "string-util.h"
#include "strv.h"
#include "strxcpyx.h"
+#include "user-util.h"
#define CONNECTIONS_MAX 4096
@@ -782,7 +784,7 @@ static int bus_setup_api(Manager *m, sd_bus *bus) {
HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
r = unit_install_bus_match(u, bus, name);
if (r < 0)
- log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m");
+ log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name);
}
r = sd_bus_add_match(
diff --git a/src/core/device.c b/src/core/device.c
index 9127d2d225..23ee7aee7e 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -24,15 +24,18 @@
#include "libudev.h"
+#include "alloc-util.h"
#include "dbus-device.h"
+#include "device.h"
#include "log.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "stat-util.h"
#include "string-util.h"
#include "swap.h"
#include "udev-util.h"
#include "unit-name.h"
#include "unit.h"
-#include "device.h"
static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
[DEVICE_DEAD] = UNIT_INACTIVE,
diff --git a/src/core/execute.c b/src/core/execute.c
index 3f2607ff1a..d751065af0 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -53,6 +53,7 @@
#include "sd-messages.h"
#include "af-list.h"
+#include "alloc-util.h"
#ifdef HAVE_APPARMOR
#include "apparmor-util.h"
#endif
@@ -60,7 +61,7 @@
#include "barrier.h"
#include "bus-endpoint.h"
#include "cap-list.h"
-#include "capability.h"
+#include "capability-util.h"
#include "def.h"
#include "env-util.h"
#include "errno-list.h"
@@ -69,6 +70,8 @@
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
+#include "glob-util.h"
#include "io-util.h"
#include "ioprio.h"
#include "log.h"
@@ -76,8 +79,10 @@
#include "missing.h"
#include "mkdir.h"
#include "namespace.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "rm-rf.h"
#ifdef HAVE_SECCOMP
#include "seccomp-util.h"
@@ -86,8 +91,10 @@
#include "selinux-util.h"
#include "signal-util.h"
#include "smack-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
+#include "syslog-util.h"
#include "terminal-util.h"
#include "unit.h"
#include "user-util.h"
diff --git a/src/core/failure-action.c b/src/core/failure-action.c
index 3412accf3e..c7c95984b7 100644
--- a/src/core/failure-action.c
+++ b/src/core/failure-action.c
@@ -23,10 +23,11 @@
#include <sys/reboot.h>
#include <linux/reboot.h>
-#include "bus-util.h"
#include "bus-error.h"
-#include "special.h"
+#include "bus-util.h"
#include "failure-action.h"
+#include "special.h"
+#include "string-table.h"
#include "terminal-util.h"
static void log_and_status(Manager *m, const char *message) {
diff --git a/src/core/hostname-setup.c b/src/core/hostname-setup.c
index f1563afff9..cc7515905d 100644
--- a/src/core/hostname-setup.c
+++ b/src/core/hostname-setup.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "alloc-util.h"
#include "fileio.h"
#include "hostname-util.h"
#include "log.h"
diff --git a/src/core/ima-setup.c b/src/core/ima-setup.c
index 0c0982b0b4..9572fa17d9 100644
--- a/src/core/ima-setup.c
+++ b/src/core/ima-setup.c
@@ -25,6 +25,7 @@
#include <errno.h>
#include "fd-util.h"
+#include "fileio.h"
#include "ima-setup.h"
#include "log.h"
#include "util.h"
diff --git a/src/core/job.c b/src/core/job.c
index 8a0e0a0ea4..120381fc3b 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -24,20 +24,23 @@
#include "sd-id128.h"
#include "sd-messages.h"
+#include "alloc-util.h"
#include "async.h"
#include "dbus-job.h"
#include "dbus.h"
#include "escape.h"
+#include "job.h"
#include "log.h"
#include "macro.h"
+#include "parse-util.h"
#include "set.h"
#include "special.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "unit.h"
#include "virt.h"
-#include "job.h"
Job* job_new_raw(Unit *unit) {
Job *j;
diff --git a/src/core/kill.c b/src/core/kill.c
index bddfa4460f..1466d5ce64 100644
--- a/src/core/kill.c
+++ b/src/core/kill.c
@@ -19,9 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "signal-util.h"
#include "kill.h"
+#include "signal-util.h"
+#include "string-table.h"
+#include "util.h"
void kill_context_init(KillContext *c) {
assert(c);
diff --git a/src/core/killall.c b/src/core/killall.c
index cb11987166..77f145b4d1 100644
--- a/src/core/killall.c
+++ b/src/core/killall.c
@@ -24,9 +24,11 @@
#include <sys/wait.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "formats-util.h"
#include "killall.h"
+#include "parse-util.h"
#include "process-util.h"
#include "set.h"
#include "string-util.h"
diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c
index 2068ffd69b..651f79a1fe 100644
--- a/src/core/kmod-setup.c
+++ b/src/core/kmod-setup.c
@@ -27,7 +27,7 @@
#endif
#include "macro.h"
-#include "capability.h"
+#include "capability-util.h"
#include "bus-util.h"
#include "kmod-setup.h"
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 31fdc48823..a30cd0967d 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -32,6 +32,7 @@
#include <sys/resource.h>
#include <sys/stat.h>
+#include "alloc-util.h"
#include "af-list.h"
#include "bus-error.h"
#include "bus-internal.h"
@@ -44,22 +45,27 @@
#include "errno-list.h"
#include "escape.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "ioprio.h"
#include "load-fragment.h"
#include "log.h"
#include "missing.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "process-util.h"
#ifdef HAVE_SECCOMP
#include "seccomp-util.h"
#endif
#include "securebits.h"
#include "signal-util.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
#include "unit-printf.h"
#include "unit.h"
#include "utf8.h"
+#include "web-util.h"
int config_parse_warn_compat(
const char *unit,
@@ -976,10 +982,11 @@ int config_parse_bounding_set(const char *unit,
void *userdata) {
uint64_t *capability_bounding_set_drop = data;
- const char *word, *state;
- size_t l;
+ uint64_t capability_bounding_set;
bool invert = false;
uint64_t sum = 0;
+ const char *prev;
+ const char *cur;
assert(filename);
assert(lvalue);
@@ -996,29 +1003,38 @@ int config_parse_bounding_set(const char *unit,
* non-inverted everywhere to have a fully normalized
* interface. */
- FOREACH_WORD_QUOTED(word, l, rvalue, state) {
- _cleanup_free_ char *t = NULL;
+ prev = cur = rvalue;
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
int cap;
+ int r;
- t = strndup(word, l);
- if (!t)
+ r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES);
+ if (r == 0)
+ break;
+ if (r == -ENOMEM)
return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage in bounding set, ignoring: %s", prev);
+ break;
+ }
- cap = capability_from_name(t);
+ cap = capability_from_name(word);
if (cap < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability in bounding set, ignoring: %s", t);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse capability in bounding set, ignoring: %s", word);
+ prev = cur;
continue;
}
sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
+ prev = cur;
}
- if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
- if (invert)
- *capability_bounding_set_drop |= sum;
+ capability_bounding_set = invert ? ~sum : sum;
+ if (*capability_bounding_set_drop && capability_bounding_set)
+ *capability_bounding_set_drop = ~(~*capability_bounding_set_drop | capability_bounding_set);
else
- *capability_bounding_set_drop |= ~sum;
+ *capability_bounding_set_drop = ~capability_bounding_set;
return 0;
}
diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c
index c72892b343..145ba2a28d 100644
--- a/src/core/machine-id-setup.c
+++ b/src/core/machine-id-setup.c
@@ -29,16 +29,22 @@
#include "sd-id128.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
+#include "hexdecoct.h"
#include "io-util.h"
#include "log.h"
#include "machine-id-setup.h"
#include "macro.h"
#include "mkdir.h"
+#include "mount-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "stat-util.h"
#include "string-util.h"
+#include "umask-util.h"
#include "util.h"
#include "virt.h"
diff --git a/src/core/main.c b/src/core/main.c
index b0ca6fa10e..593b974566 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -40,11 +40,12 @@
#include "sd-daemon.h"
#include "sd-bus.h"
+#include "alloc-util.h"
#include "architecture.h"
#include "build.h"
#include "bus-error.h"
#include "bus-util.h"
-#include "capability.h"
+#include "capability-util.h"
#include "clock-util.h"
#include "conf-parser.h"
#include "cpu-set-util.h"
@@ -55,6 +56,7 @@
#include "fdset.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "hostname-setup.h"
#include "ima-setup.h"
#include "killall.h"
@@ -67,12 +69,17 @@
#include "missing.h"
#include "mount-setup.h"
#include "pager.h"
+#include "parse-util.h"
+#include "proc-cmdline.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "selinux-setup.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "smack-setup.h"
#include "special.h"
+#include "stat-util.h"
+#include "stdio-util.h"
#include "strv.h"
#include "switch-root.h"
#include "terminal-util.h"
diff --git a/src/core/manager.c b/src/core/manager.c
index 287676ff27..b13663e702 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -40,6 +40,7 @@
#include "sd-daemon.h"
#include "sd-messages.h"
+#include "alloc-util.h"
#include "audit-fd.h"
#include "boot-timestamps.h"
#include "bus-common-errors.h"
@@ -54,6 +55,8 @@
#include "escape.h"
#include "exit-status.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "io-util.h"
#include "locale-setup.h"
@@ -62,6 +65,7 @@
#include "manager.h"
#include "missing.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
#include "process-util.h"
@@ -69,16 +73,21 @@
#include "rm-rf.h"
#include "signal-util.h"
#include "special.h"
+#include "stat-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "time-util.h"
#include "transaction.h"
+#include "umask-util.h"
#include "unit-name.h"
#include "util.h"
#include "virt.h"
#include "watchdog.h"
+#define NOTIFY_RCVBUF_SIZE (8*1024*1024)
+
/* Initial delay and the interval for printing status messages about running jobs */
#define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC)
#define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3)
@@ -682,6 +691,8 @@ static int manager_setup_notify(Manager *m) {
if (fd < 0)
return log_error_errno(errno, "Failed to allocate notification socket: %m");
+ fd_inc_rcvbuf(fd, NOTIFY_RCVBUF_SIZE);
+
if (m->running_as == MANAGER_SYSTEM)
m->notify_socket = strdup("/run/systemd/notify");
else {
@@ -1481,7 +1492,7 @@ static unsigned manager_dispatch_dbus_queue(Manager *m) {
return n;
}
-static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, char *buf, size_t n, FDSet *fds) {
+static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, const char *buf, size_t n, FDSet *fds) {
_cleanup_strv_free_ char **tags = NULL;
assert(m);
@@ -1502,9 +1513,33 @@ static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, char *
}
static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+ _cleanup_fdset_free_ FDSet *fds = NULL;
Manager *m = userdata;
+
+ char buf[NOTIFY_BUFFER_MAX+1];
+ struct iovec iovec = {
+ .iov_base = buf,
+ .iov_len = sizeof(buf)-1,
+ };
+ union {
+ struct cmsghdr cmsghdr;
+ uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
+ CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)];
+ } control = {};
+ struct msghdr msghdr = {
+ .msg_iov = &iovec,
+ .msg_iovlen = 1,
+ .msg_control = &control,
+ .msg_controllen = sizeof(control),
+ };
+
+ struct cmsghdr *cmsg;
+ struct ucred *ucred = NULL;
+ bool found = false;
+ Unit *u1, *u2, *u3;
+ int r, *fd_array = NULL;
+ unsigned n_fds = 0;
ssize_t n;
- int r;
assert(m);
assert(m->notify_fd == fd);
@@ -1514,106 +1549,80 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
return 0;
}
- for (;;) {
- _cleanup_fdset_free_ FDSet *fds = NULL;
- char buf[NOTIFY_BUFFER_MAX+1];
- struct iovec iovec = {
- .iov_base = buf,
- .iov_len = sizeof(buf)-1,
- };
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
- CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)];
- } control = {};
- struct msghdr msghdr = {
- .msg_iov = &iovec,
- .msg_iovlen = 1,
- .msg_control = &control,
- .msg_controllen = sizeof(control),
- };
- struct cmsghdr *cmsg;
- struct ucred *ucred = NULL;
- bool found = false;
- Unit *u1, *u2, *u3;
- int *fd_array = NULL;
- unsigned n_fds = 0;
-
- n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
- if (n < 0) {
- if (errno == EAGAIN || errno == EINTR)
- break;
+ n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
+ if (n < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ return 0;
- return -errno;
- }
+ return -errno;
+ }
- CMSG_FOREACH(cmsg, &msghdr) {
- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+ CMSG_FOREACH(cmsg, &msghdr) {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
- fd_array = (int*) CMSG_DATA(cmsg);
- n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+ fd_array = (int*) CMSG_DATA(cmsg);
+ n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
- } else if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_CREDENTIALS &&
- cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
+ } else if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_CREDENTIALS &&
+ cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
- ucred = (struct ucred*) CMSG_DATA(cmsg);
- }
+ ucred = (struct ucred*) CMSG_DATA(cmsg);
}
+ }
- if (n_fds > 0) {
- assert(fd_array);
+ if (n_fds > 0) {
+ assert(fd_array);
- r = fdset_new_array(&fds, fd_array, n_fds);
- if (r < 0) {
- close_many(fd_array, n_fds);
- return log_oom();
- }
+ r = fdset_new_array(&fds, fd_array, n_fds);
+ if (r < 0) {
+ close_many(fd_array, n_fds);
+ return log_oom();
}
+ }
- if (!ucred || ucred->pid <= 0) {
- log_warning("Received notify message without valid credentials. Ignoring.");
- continue;
- }
+ if (!ucred || ucred->pid <= 0) {
+ log_warning("Received notify message without valid credentials. Ignoring.");
+ return 0;
+ }
- if ((size_t) n >= sizeof(buf)) {
- log_warning("Received notify message exceeded maximum size. Ignoring.");
- continue;
- }
+ if ((size_t) n >= sizeof(buf)) {
+ log_warning("Received notify message exceeded maximum size. Ignoring.");
+ return 0;
+ }
- buf[n] = 0;
+ buf[n] = 0;
- /* Notify every unit that might be interested, but try
- * to avoid notifying the same one multiple times. */
- u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid);
- if (u1) {
- manager_invoke_notify_message(m, u1, ucred->pid, buf, n, fds);
- found = true;
- }
+ /* Notify every unit that might be interested, but try
+ * to avoid notifying the same one multiple times. */
+ u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid);
+ if (u1) {
+ manager_invoke_notify_message(m, u1, ucred->pid, buf, n, fds);
+ found = true;
+ }
- u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(ucred->pid));
- if (u2 && u2 != u1) {
- manager_invoke_notify_message(m, u2, ucred->pid, buf, n, fds);
- found = true;
- }
+ u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(ucred->pid));
+ if (u2 && u2 != u1) {
+ manager_invoke_notify_message(m, u2, ucred->pid, buf, n, fds);
+ found = true;
+ }
- u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(ucred->pid));
- if (u3 && u3 != u2 && u3 != u1) {
- manager_invoke_notify_message(m, u3, ucred->pid, buf, n, fds);
- found = true;
- }
+ u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(ucred->pid));
+ if (u3 && u3 != u2 && u3 != u1) {
+ manager_invoke_notify_message(m, u3, ucred->pid, buf, n, fds);
+ found = true;
+ }
- if (!found)
- log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid);
+ if (!found)
+ log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid);
- if (fdset_size(fds) > 0)
- log_warning("Got auxiliary fds with notification message, closing all.");
- }
+ if (fdset_size(fds) > 0)
+ log_warning("Got auxiliary fds with notification message, closing all.");
return 0;
}
-static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) {
+static void invoke_sigchld_event(Manager *m, Unit *u, const siginfo_t *si) {
assert(m);
assert(u);
assert(si);
@@ -1995,8 +2004,7 @@ int manager_loop(Manager *m) {
m->exit_code = MANAGER_OK;
/* Release the path cache */
- set_free_free(m->unit_path_cache);
- m->unit_path_cache = NULL;
+ m->unit_path_cache = set_free_free(m->unit_path_cache);
manager_check_finished(m);
@@ -2106,6 +2114,9 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
const char *msg;
int audit_fd, r;
+ if (m->running_as != MANAGER_SYSTEM)
+ return;
+
audit_fd = get_audit_fd();
if (audit_fd < 0)
return;
@@ -2115,9 +2126,6 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
if (m->n_reloading > 0)
return;
- if (m->running_as != MANAGER_SYSTEM)
- return;
-
if (u->type != UNIT_SERVICE)
return;
@@ -2766,8 +2774,7 @@ static int create_generator_dir(Manager *m, char **generator, const char *name)
return log_oom();
if (!mkdtemp(p)) {
- log_error_errno(errno, "Failed to create generator directory %s: %m",
- p);
+ log_error_errno(errno, "Failed to create generator directory %s: %m", p);
free(p);
return -errno;
}
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index 9b16eaa0e2..b2596d1cd1 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -25,22 +25,25 @@
#include <unistd.h>
#include <ftw.h>
-#include "mount-setup.h"
-#include "dev-setup.h"
+#include "alloc-util.h"
#include "bus-util.h"
+#include "cgroup-util.h"
+#include "dev-setup.h"
+#include "efivars.h"
+#include "label.h"
#include "log.h"
#include "macro.h"
-#include "util.h"
-#include "label.h"
-#include "set.h"
-#include "strv.h"
+#include "missing.h"
#include "mkdir.h"
+#include "mount-setup.h"
+#include "mount-util.h"
#include "path-util.h"
-#include "missing.h"
-#include "virt.h"
-#include "efivars.h"
+#include "set.h"
#include "smack-util.h"
-#include "cgroup-util.h"
+#include "strv.h"
+#include "user-util.h"
+#include "util.h"
+#include "virt.h"
typedef enum MountMode {
MNT_NONE = 0,
diff --git a/src/core/mount.c b/src/core/mount.c
index ebdb3503e9..950d5d76d5 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -26,6 +26,7 @@
#include "sd-messages.h"
+#include "alloc-util.h"
#include "dbus-mount.h"
#include "escape.h"
#include "exit-status.h"
@@ -35,10 +36,14 @@
#include "manager.h"
#include "mkdir.h"
#include "mount-setup.h"
+#include "mount-util.h"
#include "mount.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "process-util.h"
#include "smack-util.h"
#include "special.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
@@ -251,9 +256,10 @@ static int mount_add_mount_links(Mount *m) {
if (!path_equal(m->where, "/")) {
/* Adds in links to other mount points that might lie further
* up in the hierarchy */
- r = path_get_parent(m->where, &parent);
- if (r < 0)
- return r;
+
+ parent = dirname_malloc(m->where);
+ if (!parent)
+ return -ENOMEM;
r = unit_require_mounts_for(UNIT(m), parent);
if (r < 0)
@@ -626,19 +632,19 @@ static int mount_coldplug(Unit *u) {
if (new_state == m->state)
return 0;
- if (new_state == MOUNT_MOUNTING ||
- new_state == MOUNT_MOUNTING_DONE ||
- new_state == MOUNT_REMOUNTING ||
- new_state == MOUNT_UNMOUNTING ||
- new_state == MOUNT_MOUNTING_SIGTERM ||
- new_state == MOUNT_MOUNTING_SIGKILL ||
- new_state == MOUNT_UNMOUNTING_SIGTERM ||
- new_state == MOUNT_UNMOUNTING_SIGKILL ||
- new_state == MOUNT_REMOUNTING_SIGTERM ||
- new_state == MOUNT_REMOUNTING_SIGKILL) {
-
- if (m->control_pid <= 0)
- return -EBADMSG;
+ if (m->control_pid > 0 &&
+ pid_is_unwaited(m->control_pid) &&
+ IN_SET(new_state,
+ MOUNT_MOUNTING,
+ MOUNT_MOUNTING_DONE,
+ MOUNT_REMOUNTING,
+ MOUNT_UNMOUNTING,
+ MOUNT_MOUNTING_SIGTERM,
+ MOUNT_MOUNTING_SIGKILL,
+ MOUNT_UNMOUNTING_SIGTERM,
+ MOUNT_UNMOUNTING_SIGKILL,
+ MOUNT_REMOUNTING_SIGTERM,
+ MOUNT_REMOUNTING_SIGKILL)) {
r = unit_watch_pid(UNIT(m), m->control_pid);
if (r < 0)
diff --git a/src/core/namespace.c b/src/core/namespace.c
index 4d11d54bfe..81ba09ea5d 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -28,17 +28,22 @@
#include <unistd.h>
#include <linux/fs.h>
+#include "alloc-util.h"
#include "dev-setup.h"
#include "fd-util.h"
#include "loopback-setup.h"
#include "missing.h"
#include "mkdir.h"
+#include "mount-util.h"
#include "namespace.h"
#include "path-util.h"
#include "selinux-util.h"
#include "socket-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
+#include "umask-util.h"
+#include "user-util.h"
#include "util.h"
typedef enum MountMode {
diff --git a/src/core/path.c b/src/core/path.c
index 11054d8c78..35e1753583 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -28,10 +28,14 @@
#include "bus-util.h"
#include "dbus-path.h"
#include "fd-util.h"
+#include "fs-util.h"
+#include "glob-util.h"
#include "macro.h"
#include "mkdir.h"
#include "path.h"
#include "special.h"
+#include "stat-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "unit-name.h"
#include "unit.h"
diff --git a/src/core/scope.c b/src/core/scope.c
index 9f72851382..6bacb226e8 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -22,15 +22,17 @@
#include <errno.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "dbus-scope.h"
#include "load-dropin.h"
#include "log.h"
+#include "scope.h"
#include "special.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
#include "unit.h"
-#include "scope.h"
static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
[SCOPE_DEAD] = UNIT_INACTIVE,
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
index cf38fa0ebe..4bcdd27389 100644
--- a/src/core/selinux-access.c
+++ b/src/core/selinux-access.c
@@ -32,13 +32,16 @@
#endif
#include "sd-bus.h"
+
+#include "alloc-util.h"
+#include "audit-fd.h"
#include "bus-util.h"
-#include "util.h"
#include "log.h"
+#include "path-util.h"
#include "selinux-util.h"
-#include "audit-fd.h"
+#include "stdio-util.h"
#include "strv.h"
-#include "path-util.h"
+#include "util.h"
static bool initialized = false;
diff --git a/src/core/service.c b/src/core/service.c
index abcbd4954f..586eddd99a 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -23,6 +23,7 @@
#include <signal.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "async.h"
#include "bus-error.h"
#include "bus-kernel.h"
@@ -35,15 +36,18 @@
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "load-dropin.h"
#include "load-fragment.h"
#include "log.h"
#include "manager.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "service.h"
#include "signal-util.h"
#include "special.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
@@ -171,7 +175,7 @@ static int service_set_main_pid(Service *s, pid_t pid) {
s->main_pid = pid;
s->main_pid_known = true;
- if (get_parent_of_pid(pid, &ppid) >= 0 && ppid != getpid()) {
+ if (get_process_ppid(pid, &ppid) >= 0 && ppid != getpid()) {
log_unit_warning(UNIT(s), "Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", pid);
s->main_pid_alien = true;
} else
@@ -416,7 +420,7 @@ static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) {
}
if (fdset_size(fds) > 0)
- log_unit_warning(UNIT(s), "Tried to store more fds than FDStoreMax=%u allows, closing remaining.", s->n_fd_store_max);
+ log_unit_warning(UNIT(s), "Tried to store more fds than FileDescriptorStoreMax=%u allows, closing remaining.", s->n_fd_store_max);
return 0;
}
@@ -908,66 +912,67 @@ static int service_coldplug(Unit *u) {
assert(s);
assert(s->state == SERVICE_DEAD);
- if (s->deserialized_state != s->state) {
-
- if (IN_SET(s->deserialized_state,
- SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
- SERVICE_RELOAD,
- SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
- SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
-
- usec_t k;
+ if (s->deserialized_state == s->state)
+ return 0;
- k = IN_SET(s->deserialized_state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD) ? s->timeout_start_usec : s->timeout_stop_usec;
+ if (IN_SET(s->deserialized_state,
+ SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
+ SERVICE_RELOAD,
+ SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
+ SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
- /* For the start/stop timeouts 0 means off */
- if (k > 0) {
- r = service_arm_timer(s, k);
- if (r < 0)
- return r;
- }
- }
+ usec_t k;
- if (s->deserialized_state == SERVICE_AUTO_RESTART) {
+ k = IN_SET(s->deserialized_state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD) ? s->timeout_start_usec : s->timeout_stop_usec;
- /* The restart timeouts 0 means immediately */
- r = service_arm_timer(s, s->restart_usec);
- if (r < 0)
- return r;
- }
-
- if (pid_is_unwaited(s->main_pid) &&
- ((s->deserialized_state == SERVICE_START && IN_SET(s->type, SERVICE_FORKING, SERVICE_DBUS, SERVICE_ONESHOT, SERVICE_NOTIFY)) ||
- IN_SET(s->deserialized_state,
- SERVICE_START, SERVICE_START_POST,
- SERVICE_RUNNING, SERVICE_RELOAD,
- SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
- SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) {
- r = unit_watch_pid(UNIT(s), s->main_pid);
+ /* For the start/stop timeouts 0 means off */
+ if (k > 0) {
+ r = service_arm_timer(s, k);
if (r < 0)
return r;
}
+ }
- if (pid_is_unwaited(s->control_pid) &&
- IN_SET(s->deserialized_state,
- SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
- SERVICE_RELOAD,
- SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
- SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
- r = unit_watch_pid(UNIT(s), s->control_pid);
- if (r < 0)
- return r;
- }
+ if (s->deserialized_state == SERVICE_AUTO_RESTART) {
- if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART))
- unit_watch_all_pids(UNIT(s));
+ /* The restart timeouts 0 means immediately */
+ r = service_arm_timer(s, s->restart_usec);
+ if (r < 0)
+ return r;
+ }
- if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD))
- service_start_watchdog(s);
+ if (s->main_pid > 0 &&
+ pid_is_unwaited(s->main_pid) &&
+ ((s->deserialized_state == SERVICE_START && IN_SET(s->type, SERVICE_FORKING, SERVICE_DBUS, SERVICE_ONESHOT, SERVICE_NOTIFY)) ||
+ IN_SET(s->deserialized_state,
+ SERVICE_START, SERVICE_START_POST,
+ SERVICE_RUNNING, SERVICE_RELOAD,
+ SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
+ SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) {
+ r = unit_watch_pid(UNIT(s), s->main_pid);
+ if (r < 0)
+ return r;
+ }
- service_set_state(s, s->deserialized_state);
+ if (s->control_pid > 0 &&
+ pid_is_unwaited(s->control_pid) &&
+ IN_SET(s->deserialized_state,
+ SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
+ SERVICE_RELOAD,
+ SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
+ SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
+ r = unit_watch_pid(UNIT(s), s->control_pid);
+ if (r < 0)
+ return r;
}
+ if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART))
+ unit_watch_all_pids(UNIT(s));
+
+ if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD))
+ service_start_watchdog(s);
+
+ service_set_state(s, s->deserialized_state);
return 0;
}
diff --git a/src/core/show-status.c b/src/core/show-status.c
index 7951ea7303..e4e12a3365 100644
--- a/src/core/show-status.c
+++ b/src/core/show-status.c
@@ -19,9 +19,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "io-util.h"
+#include "parse-util.h"
+#include "show-status.h"
#include "string-util.h"
+#include "terminal-util.h"
#include "util.h"
-#include "show-status.h"
int parse_show_status(const char *v, ShowStatus *ret) {
int r;
@@ -41,3 +46,81 @@ int parse_show_status(const char *v, ShowStatus *ret) {
*ret = r ? SHOW_STATUS_YES : SHOW_STATUS_NO;
return 0;
}
+
+int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
+ static const char status_indent[] = " "; /* "[" STATUS "] " */
+ _cleanup_free_ char *s = NULL;
+ _cleanup_close_ int fd = -1;
+ struct iovec iovec[6] = {};
+ int n = 0;
+ static bool prev_ephemeral;
+
+ assert(format);
+
+ /* This is independent of logging, as status messages are
+ * optional and go exclusively to the console. */
+
+ if (vasprintf(&s, format, ap) < 0)
+ return log_oom();
+
+ fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
+ if (fd < 0)
+ return fd;
+
+ if (ellipse) {
+ char *e;
+ size_t emax, sl;
+ int c;
+
+ c = fd_columns(fd);
+ if (c <= 0)
+ c = 80;
+
+ sl = status ? sizeof(status_indent)-1 : 0;
+
+ emax = c - sl - 1;
+ if (emax < 3)
+ emax = 3;
+
+ e = ellipsize(s, emax, 50);
+ if (e) {
+ free(s);
+ s = e;
+ }
+ }
+
+ if (prev_ephemeral)
+ IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
+ prev_ephemeral = ephemeral;
+
+ if (status) {
+ if (!isempty(status)) {
+ IOVEC_SET_STRING(iovec[n++], "[");
+ IOVEC_SET_STRING(iovec[n++], status);
+ IOVEC_SET_STRING(iovec[n++], "] ");
+ } else
+ IOVEC_SET_STRING(iovec[n++], status_indent);
+ }
+
+ IOVEC_SET_STRING(iovec[n++], s);
+ if (!ephemeral)
+ IOVEC_SET_STRING(iovec[n++], "\n");
+
+ if (writev(fd, iovec, n) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) {
+ va_list ap;
+ int r;
+
+ assert(format);
+
+ va_start(ap, format);
+ r = status_vprintf(status, ellipse, ephemeral, format, ap);
+ va_end(ap);
+
+ return r;
+}
diff --git a/src/core/show-status.h b/src/core/show-status.h
index a2b2153746..c79d4acb66 100644
--- a/src/core/show-status.h
+++ b/src/core/show-status.h
@@ -21,6 +21,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdbool.h>
+
+#include "macro.h"
+
/* Manager status */
typedef enum ShowStatus {
@@ -32,3 +36,6 @@ typedef enum ShowStatus {
} ShowStatus;
int parse_show_status(const char *v, ShowStatus *ret);
+
+int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) _printf_(4,0);
+int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) _printf_(4,5);
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index 33383a4b0b..3a95b5fd72 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -31,12 +31,14 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "cgroup-util.h"
#include "def.h"
#include "fileio.h"
#include "killall.h"
#include "log.h"
#include "missing.h"
+#include "parse-util.h"
#include "process-util.h"
#include "string-util.h"
#include "switch-root.h"
diff --git a/src/core/slice.c b/src/core/slice.c
index 8fb6d28a3c..4602144150 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -21,6 +21,7 @@
#include <errno.h>
+#include "alloc-util.h"
#include "dbus-slice.h"
#include "log.h"
#include "special.h"
diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c
index 34df392184..0661ff9ecd 100644
--- a/src/core/smack-setup.c
+++ b/src/core/smack-setup.c
@@ -28,6 +28,8 @@
#include <stdlib.h>
#include <string.h>
+#include "alloc-util.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "log.h"
diff --git a/src/core/snapshot.c b/src/core/snapshot.c
index 15726c344e..ba3135f401 100644
--- a/src/core/snapshot.c
+++ b/src/core/snapshot.c
@@ -21,12 +21,15 @@
#include <errno.h>
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "dbus-snapshot.h"
+#include "parse-util.h"
+#include "parse-util.h"
+#include "snapshot.h"
#include "string-util.h"
#include "unit-name.h"
#include "unit.h"
-#include "snapshot.h"
static const UnitActiveState state_translation_table[_SNAPSHOT_STATE_MAX] = {
[SNAPSHOT_DEAD] = UNIT_INACTIVE,
diff --git a/src/core/snapshot.h b/src/core/snapshot.h
index 97747e18bd..bd52dea408 100644
--- a/src/core/snapshot.h
+++ b/src/core/snapshot.h
@@ -23,6 +23,8 @@
typedef struct Snapshot Snapshot;
+#include "unit.h"
+
struct Snapshot {
Unit meta;
diff --git a/src/core/socket.c b/src/core/socket.c
index 7f401025ed..3c7f972fbc 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -31,6 +31,7 @@
#include "sd-event.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "copy.h"
@@ -43,12 +44,15 @@
#include "log.h"
#include "missing.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "process-util.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "smack-util.h"
#include "socket.h"
#include "special.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
@@ -1168,9 +1172,9 @@ static int usbffs_dispatch_eps(SocketPort *p) {
_cleanup_free_ char *path = NULL;
int r, i, n, k;
- r = path_get_parent(p->path, &path);
- if (r < 0)
- return r;
+ path = dirname_malloc(p->path);
+ if (!path)
+ return -ENOMEM;
r = scandir(path, &ent, usbffs_select_ep, alphasort);
if (r < 0)
@@ -1451,7 +1455,9 @@ static int socket_coldplug(Unit *u) {
if (s->deserialized_state == s->state)
return 0;
- if (IN_SET(s->deserialized_state,
+ if (s->control_pid > 0 &&
+ pid_is_unwaited(s->control_pid) &&
+ IN_SET(s->deserialized_state,
SOCKET_START_PRE,
SOCKET_START_CHOWN,
SOCKET_START_POST,
@@ -1462,9 +1468,6 @@ static int socket_coldplug(Unit *u) {
SOCKET_FINAL_SIGTERM,
SOCKET_FINAL_SIGKILL)) {
- if (s->control_pid <= 0)
- return -EBADMSG;
-
r = unit_watch_pid(UNIT(s), s->control_pid);
if (r < 0)
return r;
diff --git a/src/core/swap.c b/src/core/swap.c
index d864c7b304..f626ea4d87 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -26,14 +26,18 @@
#include "libudev.h"
+#include "alloc-util.h"
#include "dbus-swap.h"
#include "escape.h"
#include "exit-status.h"
#include "fd-util.h"
#include "formats-util.h"
#include "fstab-util.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "process-util.h"
#include "special.h"
+#include "string-table.h"
#include "string-util.h"
#include "swap.h"
#include "udev-util.h"
@@ -524,16 +528,16 @@ static int swap_coldplug(Unit *u) {
if (new_state == s->state)
return 0;
- if (new_state == SWAP_ACTIVATING ||
- new_state == SWAP_ACTIVATING_SIGTERM ||
- new_state == SWAP_ACTIVATING_SIGKILL ||
- new_state == SWAP_ACTIVATING_DONE ||
- new_state == SWAP_DEACTIVATING ||
- new_state == SWAP_DEACTIVATING_SIGTERM ||
- new_state == SWAP_DEACTIVATING_SIGKILL) {
-
- if (s->control_pid <= 0)
- return -EBADMSG;
+ if (s->control_pid > 0 &&
+ pid_is_unwaited(s->control_pid) &&
+ IN_SET(new_state,
+ SWAP_ACTIVATING,
+ SWAP_ACTIVATING_SIGTERM,
+ SWAP_ACTIVATING_SIGKILL,
+ SWAP_ACTIVATING_DONE,
+ SWAP_DEACTIVATING,
+ SWAP_DEACTIVATING_SIGTERM,
+ SWAP_DEACTIVATING_SIGKILL)) {
r = unit_watch_pid(UNIT(s), s->control_pid);
if (r < 0)
diff --git a/src/core/timer.c b/src/core/timer.c
index 908d45ac73..cc2afedabf 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -21,10 +21,14 @@
#include <errno.h>
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "dbus-timer.h"
+#include "fs-util.h"
+#include "parse-util.h"
#include "special.h"
+#include "string-table.h"
#include "string-util.h"
#include "timer.h"
#include "unit-name.h"
diff --git a/src/core/transaction.c b/src/core/transaction.c
index d1c1b9a3cd..69f28c902f 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -22,10 +22,11 @@
#include <unistd.h>
#include <fcntl.h>
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-error.h"
-#include "transaction.h"
#include "terminal-util.h"
+#include "transaction.h"
static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies);
diff --git a/src/core/umount.c b/src/core/umount.c
index 8735bed7b1..9d1f7660db 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -29,6 +29,7 @@
#include "libudev.h"
+#include "alloc-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fstab-util.h"
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index 4a5c7efdb0..721c8ccce9 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "cgroup-util.h"
#include "formats-util.h"
#include "macro.h"
diff --git a/src/core/unit.c b/src/core/unit.c
index 572b1c1b78..6c130d4cd1 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -28,6 +28,7 @@
#include "sd-id128.h"
#include "sd-messages.h"
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-util.h"
#include "cgroup-util.h"
@@ -44,10 +45,12 @@
#include "macro.h"
#include "missing.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "set.h"
#include "special.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
@@ -416,12 +419,11 @@ static void unit_remove_transient(Unit *u) {
STRV_FOREACH(i, u->dropin_paths) {
_cleanup_free_ char *p = NULL;
- int r;
(void) unlink(*i);
- r = path_get_parent(*i, &p);
- if (r >= 0)
+ p = dirname_malloc(*i);
+ if (p)
(void) rmdir(p);
}
}
@@ -2326,7 +2328,7 @@ int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency
int set_unit_path(const char *p) {
/* This is mostly for debug purposes */
- if (setenv("SYSTEMD_UNIT_PATH", p, 0) < 0)
+ if (setenv("SYSTEMD_UNIT_PATH", p, 1) < 0)
return -errno;
return 0;
@@ -2509,7 +2511,7 @@ int unit_watch_bus_name(Unit *u, const char *name) {
* Otherwise, just put the name in the list. bus_setup_api() will take care later. */
r = unit_install_bus_match(u, u->manager->api_bus, name);
if (r < 0)
- return log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m");
+ return log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name);
}
r = hashmap_put(u->manager->watch_bus, name, u);
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index 78adcf18d6..ae53bac600 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -21,14 +21,18 @@
#include <errno.h>
+#include "alloc-util.h"
#include "dropin.h"
#include "fd-util.h"
+#include "fileio.h"
#include "fstab-util.h"
#include "generator.h"
#include "hashmap.h"
#include "log.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "proc-cmdline.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
index f5fb6a09fe..98fe52a81b 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -27,11 +27,14 @@
#include "sd-device.h"
+#include "alloc-util.h"
#include "ask-password-api.h"
#include "device-util.h"
#include "escape.h"
#include "fileio.h"
#include "log.h"
+#include "mount-util.h"
+#include "parse-util.h"
#include "path-util.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/dbus1-generator/dbus1-generator.c b/src/dbus1-generator/dbus1-generator.c
index 8dd75f3324..b57bf9a57d 100644
--- a/src/dbus1-generator/dbus1-generator.c
+++ b/src/dbus1-generator/dbus1-generator.c
@@ -19,11 +19,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-util.h"
#include "cgroup-util.h"
#include "conf-parser.h"
+#include "dirent-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "mkdir.h"
#include "special.h"
#include "unit-name.h"
diff --git a/src/debug-generator/debug-generator.c b/src/debug-generator/debug-generator.c
index 7f26108e9c..e16c3b9453 100644
--- a/src/debug-generator/debug-generator.c
+++ b/src/debug-generator/debug-generator.c
@@ -19,11 +19,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "strv.h"
-#include "unit-name.h"
+#include "alloc-util.h"
#include "mkdir.h"
+#include "parse-util.h"
+#include "proc-cmdline.h"
#include "string-util.h"
+#include "strv.h"
+#include "unit-name.h"
+#include "util.h"
static const char *arg_dest = "/tmp";
static char **arg_mask = NULL;
diff --git a/src/delta/delta.c b/src/delta/delta.c
index 5dbd526b9b..6c25b185ed 100644
--- a/src/delta/delta.c
+++ b/src/delta/delta.c
@@ -26,13 +26,19 @@
#include <sys/prctl.h>
#include <unistd.h>
+#include "alloc-util.h"
+#include "dirent-util.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "hashmap.h"
+#include "locale-util.h"
#include "log.h"
#include "pager.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "signal-util.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
diff --git a/src/detect-virt/detect-virt.c b/src/detect-virt/detect-virt.c
index dcf4e9749e..0a256c29be 100644
--- a/src/detect-virt/detect-virt.c
+++ b/src/detect-virt/detect-virt.c
@@ -31,7 +31,8 @@ static bool arg_quiet = false;
static enum {
ANY_VIRTUALIZATION,
ONLY_VM,
- ONLY_CONTAINER
+ ONLY_CONTAINER,
+ ONLY_CHROOT,
} arg_mode = ANY_VIRTUALIZATION;
static void help(void) {
@@ -41,6 +42,7 @@ static void help(void) {
" --version Show package version\n"
" -c --container Only detect whether we are run in a container\n"
" -v --vm Only detect whether we are run in a VM\n"
+ " -r --chroot Detect whether we are run in a chroot() environment\n"
" -q --quiet Don't output anything, just set return value\n"
, program_invocation_short_name);
}
@@ -55,7 +57,8 @@ static int parse_argv(int argc, char *argv[]) {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "container", no_argument, NULL, 'c' },
- { "vm", optional_argument, NULL, 'v' },
+ { "vm", no_argument, NULL, 'v' },
+ { "chroot", no_argument, NULL, 'r' },
{ "quiet", no_argument, NULL, 'q' },
{}
};
@@ -65,7 +68,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hqcv", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "hqcvr", options, NULL)) >= 0)
switch (c) {
@@ -88,6 +91,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_mode = ONLY_VM;
break;
+ case 'r':
+ arg_mode = ONLY_CHROOT;
+ break;
+
case '?':
return -EINVAL;
@@ -137,6 +144,15 @@ int main(int argc, char *argv[]) {
break;
+ case ONLY_CHROOT:
+ r = running_in_chroot();
+ if (r < 0) {
+ log_error_errno(r, "Failed to check for chroot() environment: %m");
+ return EXIT_FAILURE;
+ }
+
+ return r ? EXIT_SUCCESS : EXIT_FAILURE;
+
case ANY_VIRTUALIZATION:
default:
r = detect_virtualization();
diff --git a/src/escape/escape.c b/src/escape/escape.c
index 9390558554..e857affbc4 100644
--- a/src/escape/escape.c
+++ b/src/escape/escape.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "alloc-util.h"
#include "log.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 5aa247b2ae..46cfe9f851 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -24,19 +24,24 @@
#include <shadow.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "ask-password-api.h"
#include "copy.h"
+#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "hostname-util.h"
#include "locale-util.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "path-util.h"
#include "random-util.h"
+#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "time-util.h"
-#include "string-util.h"
-#include "fd-util.h"
+#include "umask-util.h"
+#include "user-util.h"
static char *arg_root = NULL;
static char *arg_locale = NULL; /* $LANG */
@@ -535,7 +540,7 @@ static int process_root_password(void) {
mkdir_parents(etc_shadow, 0755);
- lock = take_password_lock(arg_root);
+ lock = take_etc_passwd_lock(arg_root);
if (lock < 0)
return lock;
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 9c49557787..5b806a1e69 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -32,16 +32,21 @@
#include "sd-bus.h"
#include "sd-device.h"
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-util.h"
#include "device-util.h"
#include "fd-util.h"
+#include "fs-util.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "proc-cmdline.h"
#include "process-util.h"
#include "signal-util.h"
#include "socket-util.h"
#include "special.h"
+#include "stdio-util.h"
#include "util.h"
/* exit codes as defined in fsck(8) */
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 0a3917b7ba..f7c8d11ace 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -25,14 +25,20 @@
#include <string.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "fstab-util.h"
#include "generator.h"
#include "log.h"
#include "mkdir.h"
#include "mount-setup.h"
+#include "mount-util.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "proc-cmdline.h"
#include "special.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c
index 0997cc5fae..03df7365b5 100644
--- a/src/getty-generator/getty-generator.c
+++ b/src/getty-generator/getty-generator.c
@@ -24,6 +24,7 @@
#include <string.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "log.h"
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index ba97c98d6f..5ea6c86898 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -27,8 +27,10 @@
#include "libudev.h"
#include "sd-id128.h"
+#include "alloc-util.h"
#include "blkid-util.h"
#include "btrfs-util.h"
+#include "dirent-util.h"
#include "efivars.h"
#include "fd-util.h"
#include "fileio.h"
@@ -37,8 +39,12 @@
#include "gpt.h"
#include "missing.h"
#include "mkdir.h"
+#include "mount-util.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "proc-cmdline.h"
#include "special.h"
+#include "stat-util.h"
#include "string-util.h"
#include "udev-util.h"
#include "unit-name.h"
diff --git a/src/hibernate-resume/hibernate-resume-generator.c b/src/hibernate-resume/hibernate-resume-generator.c
index dff2ada384..da719f2a30 100644
--- a/src/hibernate-resume/hibernate-resume-generator.c
+++ b/src/hibernate-resume/hibernate-resume-generator.c
@@ -22,8 +22,11 @@
#include <errno.h>
#include <stdio.h>
+#include "alloc-util.h"
+#include "fstab-util.h"
#include "log.h"
#include "mkdir.h"
+#include "proc-cmdline.h"
#include "special.h"
#include "string-util.h"
#include "unit-name.h"
diff --git a/src/hibernate-resume/hibernate-resume.c b/src/hibernate-resume/hibernate-resume.c
index 1f3b169905..316a2803d3 100644
--- a/src/hibernate-resume/hibernate-resume.c
+++ b/src/hibernate-resume/hibernate-resume.c
@@ -23,9 +23,10 @@
#include <errno.h>
#include <sys/stat.h>
+#include "alloc-util.h"
+#include "fileio.h"
#include "log.h"
#include "util.h"
-#include "fileio.h"
int main(int argc, char *argv[]) {
struct stat st;
diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c
index 0724fcc16d..bf09fb8fbb 100644
--- a/src/hostname/hostnamectl.c
+++ b/src/hostname/hostnamectl.c
@@ -28,6 +28,7 @@
#include "sd-bus.h"
#include "sd-id128.h"
+#include "alloc-util.h"
#include "architecture.h"
#include "bus-error.h"
#include "bus-util.h"
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index dd508aefb5..92061532b8 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -24,16 +24,20 @@
#include <unistd.h>
#include <sys/utsname.h>
-#include "util.h"
-#include "strv.h"
+#include "alloc-util.h"
+#include "bus-util.h"
#include "def.h"
-#include "virt.h"
#include "env-util.h"
-#include "fileio-label.h"
-#include "bus-util.h"
#include "event-util.h"
-#include "selinux-util.h"
+#include "fileio-label.h"
#include "hostname-util.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "selinux-util.h"
+#include "strv.h"
+#include "user-util.h"
+#include "util.h"
+#include "virt.h"
#define VALID_DEPLOYMENT_CHARS (DIGITS LETTERS "-.:")
diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c
index 3b800e99d3..de59b797a6 100644
--- a/src/hwdb/hwdb.c
+++ b/src/hwdb/hwdb.c
@@ -22,7 +22,11 @@
#include <stdlib.h>
#include <string.h>
+#include "alloc-util.h"
#include "conf-files.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "hwdb-internal.h"
#include "hwdb-util.h"
#include "mkdir.h"
@@ -31,7 +35,6 @@
#include "strv.h"
#include "util.h"
#include "verbs.h"
-#include "fd-util.h"
/*
* Generic udev properties, key/value database based on modalias strings.
diff --git a/src/import/curl-util.c b/src/import/curl-util.c
index 455fa1e07d..4278466df1 100644
--- a/src/import/curl-util.c
+++ b/src/import/curl-util.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "curl-util.h"
#include "fd-util.h"
#include "string-util.h"
diff --git a/src/import/export-raw.c b/src/import/export-raw.c
index 24c0ec9309..103d45bf21 100644
--- a/src/import/export-raw.c
+++ b/src/import/export-raw.c
@@ -25,10 +25,12 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "btrfs-util.h"
#include "copy.h"
#include "export-raw.h"
#include "fd-util.h"
+#include "fileio.h"
#include "import-common.h"
#include "ratelimit.h"
#include "string-util.h"
diff --git a/src/import/export-tar.c b/src/import/export-tar.c
index aa9b7f1a91..2bbec661e6 100644
--- a/src/import/export-tar.c
+++ b/src/import/export-tar.c
@@ -21,9 +21,11 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "btrfs-util.h"
#include "export-tar.h"
#include "fd-util.h"
+#include "fileio.h"
#include "import-common.h"
#include "process-util.h"
#include "ratelimit.h"
diff --git a/src/import/export.c b/src/import/export.c
index 1ecd1e4e10..2b33d778d3 100644
--- a/src/import/export.c
+++ b/src/import/export.c
@@ -23,10 +23,12 @@
#include "sd-event.h"
+#include "alloc-util.h"
#include "event-util.h"
#include "export-raw.h"
#include "export-tar.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "hostname-util.h"
#include "import-util.h"
#include "machine-image.h"
diff --git a/src/import/import-common.c b/src/import/import-common.c
index d96a000f81..a8551ca9e8 100644
--- a/src/import/import-common.c
+++ b/src/import/import-common.c
@@ -25,7 +25,7 @@
#include <unistd.h>
#include "btrfs-util.h"
-#include "capability.h"
+#include "capability-util.h"
#include "fd-util.h"
#include "import-common.h"
#include "signal-util.h"
diff --git a/src/import/import-compress.c b/src/import/import-compress.c
index d6b8133036..d4ff178f60 100644
--- a/src/import/import-compress.c
+++ b/src/import/import-compress.c
@@ -19,8 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
#include "import-compress.h"
+#include "string-table.h"
+#include "util.h"
void import_compress_free(ImportCompress *c) {
assert(c);
diff --git a/src/import/import-raw.c b/src/import/import-raw.c
index a34f30abfc..2193d1d7f1 100644
--- a/src/import/import-raw.c
+++ b/src/import/import-raw.c
@@ -24,9 +24,13 @@
#include "sd-daemon.h"
#include "sd-event.h"
+#include "alloc-util.h"
#include "btrfs-util.h"
+#include "chattr-util.h"
#include "copy.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "hostname-util.h"
#include "import-common.h"
#include "import-compress.h"
diff --git a/src/import/import-tar.c b/src/import/import-tar.c
index 9aade0f430..2ae1d88168 100644
--- a/src/import/import-tar.c
+++ b/src/import/import-tar.c
@@ -24,9 +24,12 @@
#include "sd-daemon.h"
#include "sd-event.h"
+#include "alloc-util.h"
#include "btrfs-util.h"
#include "copy.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "hostname-util.h"
#include "import-common.h"
#include "import-compress.h"
diff --git a/src/import/import.c b/src/import/import.c
index e50ded9219..018b94d4c4 100644
--- a/src/import/import.c
+++ b/src/import/import.c
@@ -23,8 +23,10 @@
#include "sd-event.h"
+#include "alloc-util.h"
#include "event-util.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "hostname-util.h"
#include "import-raw.h"
#include "import-tar.h"
diff --git a/src/import/importd.c b/src/import/importd.c
index b712cedcc6..4228681cea 100644
--- a/src/import/importd.c
+++ b/src/import/importd.c
@@ -23,6 +23,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-util.h"
#include "def.h"
@@ -32,12 +33,17 @@
#include "machine-pool.h"
#include "missing.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "signal-util.h"
#include "socket-util.h"
+#include "string-table.h"
#include "strv.h"
+#include "syslog-util.h"
+#include "user-util.h"
#include "util.h"
+#include "web-util.h"
typedef struct Transfer Transfer;
typedef struct Manager Manager;
diff --git a/src/import/pull-common.c b/src/import/pull-common.c
index f465154b1d..d6567ba7ee 100644
--- a/src/import/pull-common.c
+++ b/src/import/pull-common.c
@@ -21,12 +21,15 @@
#include <sys/prctl.h>
+#include "alloc-util.h"
#include "btrfs-util.h"
-#include "capability.h"
+#include "capability-util.h"
#include "copy.h"
+#include "dirent-util.h"
#include "escape.h"
#include "fd-util.h"
#include "io-util.h"
+#include "path-util.h"
#include "process-util.h"
#include "pull-common.h"
#include "pull-job.h"
@@ -36,6 +39,7 @@
#include "string-util.h"
#include "strv.h"
#include "util.h"
+#include "web-util.h"
#define FILENAME_ESCAPE "/.#\"\'"
#define HASH_URL_THRESHOLD_LENGTH (_POSIX_PATH_MAX - 16)
diff --git a/src/import/pull-dkr.c b/src/import/pull-dkr.c
index 1cd9e7b0bd..831470ff13 100644
--- a/src/import/pull-dkr.c
+++ b/src/import/pull-dkr.c
@@ -24,10 +24,13 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "aufs-util.h"
#include "btrfs-util.h"
#include "curl-util.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "hostname-util.h"
#include "import-common.h"
#include "import-util.h"
@@ -42,6 +45,7 @@
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
+#include "web-util.h"
typedef enum DkrProgress {
DKR_SEARCHING,
@@ -479,13 +483,13 @@ static int dkr_pull_make_local_copy(DkrPull *i, DkrPullVersion version) {
if (!i->final_path) {
i->final_path = strjoin(i->image_root, "/.dkr-", i->id, NULL);
if (!i->final_path)
- return log_oom();
+ return -ENOMEM;
}
if (version == DKR_PULL_V2) {
- r = path_get_parent(i->image_root, &p);
- if (r < 0)
- return r;
+ p = dirname_malloc(i->image_root);
+ if (!p)
+ return -ENOMEM;
}
r = pull_make_local_copy(i->final_path, p ?: i->image_root, i->local, i->force_local);
diff --git a/src/import/pull-job.c b/src/import/pull-job.c
index 4736306de2..824fa246ec 100644
--- a/src/import/pull-job.c
+++ b/src/import/pull-job.c
@@ -21,12 +21,16 @@
#include <sys/xattr.h>
+#include "alloc-util.h"
#include "fd-util.h"
+#include "hexdecoct.h"
#include "io-util.h"
#include "machine-pool.h"
+#include "parse-util.h"
#include "pull-job.h"
#include "string-util.h"
#include "strv.h"
+#include "xattr-util.h"
PullJob* pull_job_unref(PullJob *j) {
if (!j)
diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c
index 848a4fcd44..394131680d 100644
--- a/src/import/pull-raw.c
+++ b/src/import/pull-raw.c
@@ -25,10 +25,14 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "btrfs-util.h"
+#include "chattr-util.h"
#include "copy.h"
#include "curl-util.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "hostname-util.h"
#include "import-common.h"
#include "import-util.h"
@@ -44,6 +48,7 @@
#include "strv.h"
#include "utf8.h"
#include "util.h"
+#include "web-util.h"
typedef enum RawProgress {
RAW_DOWNLOADING,
diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c
index 3540bbff41..26c0bc5866 100644
--- a/src/import/pull-tar.c
+++ b/src/import/pull-tar.c
@@ -24,10 +24,13 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "btrfs-util.h"
#include "copy.h"
#include "curl-util.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "hostname-util.h"
#include "import-common.h"
#include "import-util.h"
@@ -43,6 +46,7 @@
#include "strv.h"
#include "utf8.h"
#include "util.h"
+#include "web-util.h"
typedef enum TarProgress {
TAR_DOWNLOADING,
diff --git a/src/import/pull.c b/src/import/pull.c
index 73d5f391c2..39f5b2d8e4 100644
--- a/src/import/pull.c
+++ b/src/import/pull.c
@@ -23,16 +23,19 @@
#include "sd-event.h"
+#include "alloc-util.h"
#include "event-util.h"
#include "hostname-util.h"
#include "import-util.h"
#include "machine-image.h"
+#include "parse-util.h"
#include "pull-dkr.h"
#include "pull-raw.h"
#include "pull-tar.h"
#include "signal-util.h"
#include "string-util.h"
#include "verbs.h"
+#include "web-util.h"
static bool arg_force = false;
static const char *arg_image_root = "/var/lib/machines";
diff --git a/src/import/qcow2-util.c b/src/import/qcow2-util.c
index fd3cf1b0e3..47dabaa86e 100644
--- a/src/import/qcow2-util.c
+++ b/src/import/qcow2-util.c
@@ -21,10 +21,11 @@
#include <zlib.h>
-#include "util.h"
-#include "sparse-endian.h"
-#include "qcow2-util.h"
+#include "alloc-util.h"
#include "btrfs-util.h"
+#include "qcow2-util.h"
+#include "sparse-endian.h"
+#include "util.h"
#define QCOW2_MAGIC 0x514649fb
diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c
index 2b374c0288..f1cf31a4a8 100644
--- a/src/initctl/initctl.c
+++ b/src/initctl/initctl.c
@@ -28,6 +28,7 @@
#include "sd-bus.h"
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "def.h"
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
index 92ef723aff..6b93a758f6 100644
--- a/src/journal-remote/journal-gatewayd.c
+++ b/src/journal-remote/journal-gatewayd.c
@@ -33,6 +33,7 @@
#include "sd-daemon.h"
#include "sd-journal.h"
+#include "alloc-util.h"
#include "bus-util.h"
#include "fd-util.h"
#include "fileio.h"
@@ -40,6 +41,7 @@
#include "log.h"
#include "logs-show.h"
#include "microhttpd-util.h"
+#include "parse-util.h"
#include "sigbus.h"
#include "util.h"
diff --git a/src/journal-remote/journal-remote-parse.c b/src/journal-remote/journal-remote-parse.c
index bb299e378c..3ff40228a0 100644
--- a/src/journal-remote/journal-remote-parse.c
+++ b/src/journal-remote/journal-remote-parse.c
@@ -19,9 +19,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "fd-util.h"
#include "journal-remote-parse.h"
#include "journald-native.h"
+#include "parse-util.h"
#include "string-util.h"
#define LINE_CHUNK 8*1024u
diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c
index 40f4ff8e58..d8250378b0 100644
--- a/src/journal-remote/journal-remote-write.c
+++ b/src/journal-remote/journal-remote-write.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "journal-remote.h"
int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len) {
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index de207f8d24..dc69bb8679 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -35,6 +35,7 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "conf-parser.h"
#include "escape.h"
#include "fd-util.h"
@@ -44,8 +45,12 @@
#include "journal-remote.h"
#include "journald-native.h"
#include "macro.h"
+#include "parse-util.h"
#include "signal-util.h"
#include "socket-util.h"
+#include "stat-util.h"
+#include "stdio-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
@@ -643,11 +648,12 @@ static int setup_microhttpd_server(RemoteServer *s,
{ MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free},
{ MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger},
{ MHD_OPTION_LISTEN_SOCKET, fd},
+ { MHD_OPTION_CONNECTION_MEMORY_LIMIT, DATA_SIZE_MAX},
{ MHD_OPTION_END},
{ MHD_OPTION_END},
{ MHD_OPTION_END},
{ MHD_OPTION_END}};
- int opts_pos = 3;
+ int opts_pos = 4;
int flags =
MHD_USE_DEBUG |
MHD_USE_DUAL_STACK |
@@ -1410,18 +1416,21 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_GNUTLS_LOG: {
#ifdef HAVE_GNUTLS
- const char *word, *state;
- size_t size;
+ const char* p = optarg;
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
- FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
- char *cat;
+ r = extract_first_word(&p, &word, ",", 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --gnutls-log= argument: %m");
- cat = strndup(word, size);
- if (!cat)
- return log_oom();
+ if (r == 0)
+ break;
- if (strv_consume(&arg_gnutls_log, cat) < 0)
+ if (strv_push(&arg_gnutls_log, word) < 0)
return log_oom();
+
+ word = NULL;
}
break;
#else
diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c
index 6b3ad924a7..3ee6d32bf7 100644
--- a/src/journal-remote/journal-upload-journal.c
+++ b/src/journal-remote/journal-upload-journal.c
@@ -1,11 +1,33 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Zbigniew Jędrzejewski-Szmek
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
#include <stdbool.h>
#include <curl/curl.h>
-#include "util.h"
+#include "alloc-util.h"
+#include "journal-upload.h"
#include "log.h"
#include "utf8.h"
-#include "journal-upload.h"
+#include "util.h"
/**
* Write up to size bytes to buf. Return negative on error, and number of
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
index a945a9971a..7d274d2fc9 100644
--- a/src/journal-remote/journal-upload.c
+++ b/src/journal-remote/journal-upload.c
@@ -27,13 +27,16 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "conf-parser.h"
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
+#include "glob-util.h"
#include "journal-upload.h"
#include "log.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "sigbus.h"
#include "signal-util.h"
#include "string-util.h"
diff --git a/src/journal-remote/microhttpd-util.c b/src/journal-remote/microhttpd-util.c
index df068a089c..b2c398a845 100644
--- a/src/journal-remote/microhttpd-util.c
+++ b/src/journal-remote/microhttpd-util.c
@@ -29,6 +29,7 @@
#include <gnutls/x509.h>
#endif
+#include "alloc-util.h"
#include "log.h"
#include "macro.h"
#include "string-util.h"
diff --git a/src/journal/cat.c b/src/journal/cat.c
index ff1887604a..7fd4198df8 100644
--- a/src/journal/cat.c
+++ b/src/journal/cat.c
@@ -29,7 +29,9 @@
#include "sd-journal.h"
#include "fd-util.h"
+#include "parse-util.h"
#include "string-util.h"
+#include "syslog-util.h"
#include "util.h"
static char *arg_identifier = NULL;
diff --git a/src/journal/catalog.c b/src/journal/catalog.c
index d5bc17b4b6..95a6857472 100644
--- a/src/journal/catalog.c
+++ b/src/journal/catalog.c
@@ -29,12 +29,15 @@
#include "sd-id128.h"
+#include "alloc-util.h"
#include "catalog.h"
#include "conf-files.h"
#include "fd-util.h"
+#include "fileio.h"
#include "hashmap.h"
#include "log.h"
#include "mkdir.h"
+#include "path-util.h"
#include "siphash24.h"
#include "sparse-endian.h"
#include "strbuf.h"
diff --git a/src/journal/compress.c b/src/journal/compress.c
index 9308e8b789..e1ca0a8818 100644
--- a/src/journal/compress.c
+++ b/src/journal/compress.c
@@ -33,12 +33,14 @@
#include <lz4frame.h>
#endif
+#include "alloc-util.h"
#include "compress.h"
#include "fd-util.h"
#include "io-util.h"
#include "journal-def.h"
#include "macro.h"
#include "sparse-endian.h"
+#include "string-table.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/journal/coredump-vacuum.c b/src/journal/coredump-vacuum.c
index bad6ea4242..39bc2e4270 100644
--- a/src/journal/coredump-vacuum.c
+++ b/src/journal/coredump-vacuum.c
@@ -21,7 +21,9 @@
#include <sys/statvfs.h>
+#include "alloc-util.h"
#include "coredump-vacuum.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "hashmap.h"
#include "macro.h"
diff --git a/src/journal/coredump.c b/src/journal/coredump.c
index 7336db219b..2e543537f6 100644
--- a/src/journal/coredump.c
+++ b/src/journal/coredump.c
@@ -34,22 +34,28 @@
#include "sd-login.h"
#include "acl-util.h"
-#include "capability.h"
+#include "alloc-util.h"
+#include "capability-util.h"
#include "cgroup-util.h"
#include "compress.h"
#include "conf-parser.h"
#include "copy.h"
#include "coredump-vacuum.h"
+#include "dirent-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
+#include "io-util.h"
#include "journald-native.h"
#include "log.h"
#include "macro.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "process-util.h"
#include "special.h"
#include "stacktrace.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c
index f891ddffc6..af4d051138 100644
--- a/src/journal/coredumpctl.c
+++ b/src/journal/coredumpctl.c
@@ -28,12 +28,15 @@
#include "sd-journal.h"
+#include "alloc-util.h"
#include "compress.h"
#include "fd-util.h"
+#include "fileio.h"
#include "journal-internal.h"
#include "log.h"
#include "macro.h"
#include "pager.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "set.h"
@@ -41,8 +44,8 @@
#include "signal-util.h"
#include "string-util.h"
#include "terminal-util.h"
-#include "util.h"
#include "user-util.h"
+#include "util.h"
static enum {
ACTION_NONE,
diff --git a/src/journal/fsprg.h b/src/journal/fsprg.h
index 150d034828..5959b1fed2 100644
--- a/src/journal/fsprg.h
+++ b/src/journal/fsprg.h
@@ -29,6 +29,7 @@
#include <inttypes.h>
#include "macro.h"
+#include "util.h"
#ifdef __cplusplus
extern "C" {
diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c
index dc51a5ab2f..0c4ac5cdc3 100644
--- a/src/journal/journal-authenticate.c
+++ b/src/journal/journal-authenticate.c
@@ -27,6 +27,7 @@
#include "journal-authenticate.h"
#include "journal-def.h"
#include "journal-file.h"
+#include "hexdecoct.h"
static uint64_t journal_file_tag_seqnum(JournalFile *f) {
uint64_t r;
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index f193cb90ce..12b39dbb27 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -28,15 +28,19 @@
#include <sys/uio.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "btrfs-util.h"
+#include "chattr-util.h"
#include "compress.h"
#include "fd-util.h"
#include "journal-authenticate.h"
#include "journal-def.h"
#include "journal-file.h"
#include "lookup3.h"
+#include "parse-util.h"
#include "random-util.h"
#include "string-util.h"
+#include "xattr-util.h"
#define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem))
#define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem))
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index f388c30d2e..fa5dee73c3 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -31,10 +31,13 @@
#include "sd-journal.h"
+#include "alloc-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "io-util.h"
#include "memfd-util.h"
#include "socket-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c
index dca5bf5000..4b5fc76eb1 100644
--- a/src/journal/journal-vacuum.c
+++ b/src/journal/journal-vacuum.c
@@ -25,12 +25,16 @@
#include "sd-id128.h"
+#include "alloc-util.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "journal-def.h"
#include "journal-file.h"
#include "journal-vacuum.h"
+#include "parse-util.h"
#include "string-util.h"
#include "util.h"
+#include "xattr-util.h"
struct vacuum_info {
uint64_t usage;
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index de4f73a471..b78ce98b17 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -24,8 +24,10 @@
#include <fcntl.h>
#include <stddef.h>
+#include "alloc-util.h"
#include "compress.h"
#include "fd-util.h"
+#include "fileio.h"
#include "journal-authenticate.h"
#include "journal-def.h"
#include "journal-file.h"
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 6e452a4d51..a35783e3ff 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -39,12 +39,16 @@
#include "sd-journal.h"
#include "acl-util.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "catalog.h"
+#include "chattr-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "fsprg.h"
+#include "glob-util.h"
#include "hostname-util.h"
#include "io-util.h"
#include "journal-def.h"
@@ -52,14 +56,18 @@
#include "journal-qrcode.h"
#include "journal-vacuum.h"
#include "journal-verify.h"
+#include "locale-util.h"
#include "log.h"
#include "logs-show.h"
#include "mkdir.h"
#include "pager.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "rlimit-util.h"
#include "set.h"
#include "sigbus.h"
#include "strv.h"
+#include "syslog-util.h"
#include "terminal-util.h"
#include "unit-name.h"
#include "user-util.h"
diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c
index 4c102fd530..3c13fe0d67 100644
--- a/src/journal/journald-audit.c
+++ b/src/journal/journald-audit.c
@@ -19,8 +19,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "audit-type.h"
#include "fd-util.h"
+#include "hexdecoct.h"
+#include "io-util.h"
#include "journald-audit.h"
#include "missing.h"
#include "string-util.h"
diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c
index 5f3eb05275..860832cfc8 100644
--- a/src/journal/journald-console.c
+++ b/src/journal/journald-console.c
@@ -23,13 +23,17 @@
#include <fcntl.h>
#include <sys/socket.h>
+#include "alloc-util.h"
+#include "fd-util.h"
#include "fileio.h"
-#include "journald-server.h"
-#include "journald-console.h"
#include "formats-util.h"
+#include "io-util.h"
+#include "journald-console.h"
+#include "journald-server.h"
+#include "parse-util.h"
#include "process-util.h"
+#include "stdio-util.h"
#include "terminal-util.h"
-#include "fd-util.h"
static bool prefix_timestamp(void) {
diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c
index 5a05632e56..489f6f689c 100644
--- a/src/journal/journald-kmsg.c
+++ b/src/journal/journald-kmsg.c
@@ -31,10 +31,13 @@
#include "escape.h"
#include "fd-util.h"
#include "formats-util.h"
+#include "io-util.h"
#include "journald-kmsg.h"
#include "journald-server.h"
#include "journald-syslog.h"
+#include "parse-util.h"
#include "process-util.h"
+#include "stdio-util.h"
#include "string-util.h"
void server_forward_kmsg(
diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
index 7d4aac687e..6fff4fe473 100644
--- a/src/journal/journald-native.c
+++ b/src/journal/journald-native.c
@@ -24,7 +24,10 @@
#include <sys/mman.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
+#include "fs-util.h"
+#include "io-util.h"
#include "journald-console.h"
#include "journald-kmsg.h"
#include "journald-native.h"
@@ -32,6 +35,7 @@
#include "journald-syslog.h"
#include "journald-wall.h"
#include "memfd-util.h"
+#include "parse-util.h"
#include "path-util.h"
#include "selinux-util.h"
#include "socket-util.h"
diff --git a/src/journal/journald-rate-limit.c b/src/journal/journald-rate-limit.c
index 6e9557c06e..434ddc8ac9 100644
--- a/src/journal/journald-rate-limit.c
+++ b/src/journal/journald-rate-limit.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include <string.h>
+#include "alloc-util.h"
#include "hashmap.h"
#include "list.h"
#include "random-util.h"
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 7cefea323e..299b0a848f 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -34,13 +34,18 @@
#include "sd-messages.h"
#include "acl-util.h"
+#include "alloc-util.h"
+#include "audit-util.h"
#include "cgroup-util.h"
#include "conf-parser.h"
+#include "dirent-util.h"
#include "extract-word.h"
#include "fd-util.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "hostname-util.h"
+#include "io-util.h"
#include "journal-authenticate.h"
#include "journal-file.h"
#include "journal-internal.h"
@@ -54,11 +59,14 @@
#include "journald-syslog.h"
#include "missing.h"
#include "mkdir.h"
+#include "parse-util.h"
+#include "proc-cmdline.h"
#include "process-util.h"
#include "rm-rf.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "socket-util.h"
+#include "string-table.h"
#include "string-util.h"
#define USER_JOURNALS_MAX 1024
@@ -70,6 +78,8 @@
#define RECHECK_SPACE_USEC (30*USEC_PER_SEC)
+#define NOTIFY_SNDBUF_SIZE (8*1024*1024)
+
static int determine_space_for(
Server *s,
JournalMetrics *metrics,
@@ -1449,6 +1459,126 @@ static int server_open_hostname(Server *s) {
return 0;
}
+static int dispatch_notify_event(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
+ Server *s = userdata;
+ int r;
+
+ assert(s);
+ assert(s->notify_event_source == es);
+ assert(s->notify_fd == fd);
+
+ if (revents != EPOLLOUT) {
+ log_error("Invalid events on notify file descriptor.");
+ return -EINVAL;
+ }
+
+ /* The $NOTIFY_SOCKET is writable again, now send exactly one
+ * message on it. Either it's the initial READY=1 event or an
+ * stdout stream event. If there's nothing to write anymore,
+ * turn our event source off. The next time there's something
+ * to send it will be turned on again. */
+
+ if (!s->sent_notify_ready) {
+ static const char p[] =
+ "READY=1\n"
+ "STATUS=Processing requests...";
+ ssize_t l;
+
+ l = send(s->notify_fd, p, strlen(p), MSG_DONTWAIT);
+ if (l < 0) {
+ if (errno == EAGAIN)
+ return 0;
+
+ return log_error_errno(errno, "Failed to send READY=1 notification message: %m");
+ }
+
+ s->sent_notify_ready = true;
+ log_debug("Sent READY=1 notification.");
+
+ } else if (s->stdout_streams_notify_queue)
+ /* Dispatch one stream notification event */
+ stdout_stream_send_notify(s->stdout_streams_notify_queue);
+
+ /* Leave us enabled if there's still more to to do. */
+ if (s->stdout_streams_notify_queue)
+ return 0;
+
+ /* There was nothing to do anymore, let's turn ourselves off. */
+ r = sd_event_source_set_enabled(es, SD_EVENT_OFF);
+ if (r < 0)
+ return log_error_errno(r, "Failed to turn off notify event source: %m");
+
+ return 0;
+}
+
+static int server_connect_notify(Server *s) {
+ union sockaddr_union sa = {
+ .un.sun_family = AF_UNIX,
+ };
+ const char *e;
+ int r;
+
+ assert(s);
+ assert(s->notify_fd < 0);
+ assert(!s->notify_event_source);
+
+ /*
+ So here's the problem: we'd like to send notification
+ messages to PID 1, but we cannot do that via sd_notify(),
+ since that's synchronous, and we might end up blocking on
+ it. Specifically: given that PID 1 might block on
+ dbus-daemon during IPC, and dbus-daemon is logging to us,
+ and might hence block on us, we might end up in a deadlock
+ if we block on sending PID 1 notification messages -- by
+ generating a full blocking circle. To avoid this, let's
+ create a non-blocking socket, and connect it to the
+ notification socket, and then wait for POLLOUT before we
+ send anything. This should efficiently avoid any deadlocks,
+ as we'll never block on PID 1, hence PID 1 can safely block
+ on dbus-daemon which can safely block on us again.
+
+ Don't think that this issue is real? It is, see:
+ https://github.com/systemd/systemd/issues/1505
+ */
+
+ e = getenv("NOTIFY_SOCKET");
+ if (!e)
+ return 0;
+
+ if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
+ log_error("NOTIFY_SOCKET set to an invalid value: %s", e);
+ return -EINVAL;
+ }
+
+ if (strlen(e) > sizeof(sa.un.sun_path)) {
+ log_error("NOTIFY_SOCKET path too long: %s", e);
+ return -EINVAL;
+ }
+
+ s->notify_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ if (s->notify_fd < 0)
+ return log_error_errno(errno, "Failed to create notify socket: %m");
+
+ (void) fd_inc_sndbuf(s->notify_fd, NOTIFY_SNDBUF_SIZE);
+
+ strncpy(sa.un.sun_path, e, sizeof(sa.un.sun_path));
+ if (sa.un.sun_path[0] == '@')
+ sa.un.sun_path[0] = 0;
+
+ r = connect(s->notify_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(e));
+ if (r < 0)
+ return log_error_errno(errno, "Failed to connect to notify socket: %m");
+
+ r = sd_event_add_io(s->event, &s->notify_event_source, s->notify_fd, EPOLLOUT, dispatch_notify_event, s);
+ if (r < 0)
+ return log_error_errno(r, "Failed to watch notification socket: %m");
+
+ /* This should fire pretty soon, which we'll use to send the
+ * READY=1 event. */
+
+ return 0;
+}
+
int server_init(Server *s) {
_cleanup_fdset_free_ FDSet *fds = NULL;
int n, r, fd;
@@ -1457,7 +1587,7 @@ int server_init(Server *s) {
assert(s);
zero(*s);
- s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->audit_fd = s->hostname_fd = -1;
+ s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->audit_fd = s->hostname_fd = s->notify_fd = -1;
s->compress = true;
s->seal = true;
@@ -1503,8 +1633,6 @@ int server_init(Server *s) {
if (r < 0)
return log_error_errno(r, "Failed to create event loop: %m");
- sd_event_set_watchdog(s->event, true);
-
n = sd_listen_fds(true);
if (n < 0)
return log_error_errno(n, "Failed to read listening file descriptors from environment: %m");
@@ -1629,6 +1757,8 @@ int server_init(Server *s) {
server_cache_boot_id(s);
server_cache_machine_id(s);
+ (void) server_connect_notify(s);
+
return system_journal_open(s, false);
}
@@ -1677,6 +1807,7 @@ void server_done(Server *s) {
sd_event_source_unref(s->sigterm_event_source);
sd_event_source_unref(s->sigint_event_source);
sd_event_source_unref(s->hostname_event_source);
+ sd_event_source_unref(s->notify_event_source);
sd_event_unref(s->event);
safe_close(s->syslog_fd);
@@ -1685,6 +1816,7 @@ void server_done(Server *s) {
safe_close(s->dev_kmsg_fd);
safe_close(s->audit_fd);
safe_close(s->hostname_fd);
+ safe_close(s->notify_fd);
if (s->rate_limit)
journal_rate_limit_free(s->rate_limit);
diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h
index 535c0ab9ab..170602ea16 100644
--- a/src/journal/journald-server.h
+++ b/src/journal/journald-server.h
@@ -25,10 +25,13 @@
#include <sys/types.h>
#include "sd-event.h"
-#include "journal-file.h"
+
+typedef struct Server Server;
+
#include "hashmap.h"
-#include "audit.h"
+#include "journal-file.h"
#include "journald-rate-limit.h"
+#include "journald-stream.h"
#include "list.h"
typedef enum Storage {
@@ -48,15 +51,14 @@ typedef enum SplitMode {
_SPLIT_INVALID = -1
} SplitMode;
-typedef struct StdoutStream StdoutStream;
-
-typedef struct Server {
+struct Server {
int syslog_fd;
int native_fd;
int stdout_fd;
int dev_kmsg_fd;
int audit_fd;
int hostname_fd;
+ int notify_fd;
sd_event *event;
@@ -71,6 +73,7 @@ typedef struct Server {
sd_event_source *sigterm_event_source;
sd_event_source *sigint_event_source;
sd_event_source *hostname_event_source;
+ sd_event_source *notify_event_source;
JournalFile *runtime_journal;
JournalFile *system_journal;
@@ -111,6 +114,7 @@ typedef struct Server {
usec_t oldest_file_usec;
LIST_HEAD(StdoutStream, stdout_streams);
+ LIST_HEAD(StdoutStream, stdout_streams_notify_queue);
unsigned n_stdout_streams;
char *tty_path;
@@ -132,6 +136,7 @@ typedef struct Server {
struct udev *udev;
+ bool sent_notify_ready;
bool sync_scheduled;
char machine_id_field[sizeof("_MACHINE_ID=") + 32];
@@ -140,7 +145,7 @@ typedef struct Server {
/* Cached cgroup root, so that we don't have to query that all the time */
char *cgroup_root;
-} Server;
+};
#define SERVER_MACHINE_ID(s) ((s)->machine_id_field + strlen("_MACHINE_ID="))
diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
index 0dd511519c..fb6afee171 100644
--- a/src/journal/journald-stream.c
+++ b/src/journal/journald-stream.c
@@ -29,9 +29,12 @@
#include "sd-daemon.h"
#include "sd-event.h"
+#include "alloc-util.h"
+#include "dirent-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
+#include "io-util.h"
#include "journald-console.h"
#include "journald-kmsg.h"
#include "journald-server.h"
@@ -39,9 +42,12 @@
#include "journald-syslog.h"
#include "journald-wall.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "selinux-util.h"
#include "socket-util.h"
+#include "stdio-util.h"
#include "string-util.h"
+#include "syslog-util.h"
#define STDOUT_STREAMS_MAX 4096
@@ -73,6 +79,7 @@ struct StdoutStream {
bool forward_to_console:1;
bool fdstore:1;
+ bool in_notify_queue:1;
char buffer[LINE_MAX+1];
size_t length;
@@ -82,6 +89,7 @@ struct StdoutStream {
char *state_file;
LIST_FIELDS(StdoutStream, stdout_stream);
+ LIST_FIELDS(StdoutStream, stdout_stream_notify_queue);
};
void stdout_stream_free(StdoutStream *s) {
@@ -92,6 +100,9 @@ void stdout_stream_free(StdoutStream *s) {
assert(s->server->n_stdout_streams > 0);
s->server->n_stdout_streams --;
LIST_REMOVE(stdout_stream, s->server->stdout_streams, s);
+
+ if (s->in_notify_queue)
+ LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
}
if (s->event_source) {
@@ -115,7 +126,7 @@ static void stdout_stream_destroy(StdoutStream *s) {
return;
if (s->state_file)
- unlink(s->state_file);
+ (void) unlink(s->state_file);
stdout_stream_free(s);
}
@@ -194,11 +205,15 @@ static int stdout_stream_save(StdoutStream *s) {
goto fail;
}
- /* Store the connection fd in PID 1, so that we get it passed
- * in again on next start */
- if (!s->fdstore) {
- sd_pid_notify_with_fds(0, false, "FDSTORE=1", &s->fd, 1);
- s->fdstore = true;
+ if (!s->fdstore && !s->in_notify_queue) {
+ LIST_PREPEND(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
+ s->in_notify_queue = true;
+
+ if (s->server->notify_event_source) {
+ r = sd_event_source_set_enabled(s->server->notify_event_source, SD_EVENT_ON);
+ if (r < 0)
+ log_warning_errno(r, "Failed to enable notify event source: %m");
+ }
}
return 0;
@@ -723,3 +738,50 @@ int server_open_stdout_socket(Server *s) {
return 0;
}
+
+void stdout_stream_send_notify(StdoutStream *s) {
+ struct iovec iovec = {
+ .iov_base = (char*) "FDSTORE=1",
+ .iov_len = strlen("FDSTORE=1"),
+ };
+ struct msghdr msghdr = {
+ .msg_iov = &iovec,
+ .msg_iovlen = 1,
+ };
+ struct cmsghdr *cmsg;
+ ssize_t l;
+
+ assert(s);
+ assert(!s->fdstore);
+ assert(s->in_notify_queue);
+ assert(s->server);
+ assert(s->server->notify_fd >= 0);
+
+ /* Store the connection fd in PID 1, so that we get it passed
+ * in again on next start */
+
+ msghdr.msg_controllen = CMSG_SPACE(sizeof(int));
+ msghdr.msg_control = alloca0(msghdr.msg_controllen);
+
+ cmsg = CMSG_FIRSTHDR(&msghdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+
+ memcpy(CMSG_DATA(cmsg), &s->fd, sizeof(int));
+
+ l = sendmsg(s->server->notify_fd, &msghdr, MSG_DONTWAIT|MSG_NOSIGNAL);
+ if (l < 0) {
+ if (errno == EAGAIN)
+ return;
+
+ log_error_errno(errno, "Failed to send stream file descriptor to service manager: %m");
+ } else {
+ log_debug("Successfully sent stream file descriptor to service manager.");
+ s->fdstore = 1;
+ }
+
+ LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
+ s->in_notify_queue = false;
+
+}
diff --git a/src/journal/journald-stream.h b/src/journal/journald-stream.h
index 257dce45df..e3497f0ded 100644
--- a/src/journal/journald-stream.h
+++ b/src/journal/journald-stream.h
@@ -21,9 +21,13 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+typedef struct StdoutStream StdoutStream;
+
#include "fdset.h"
#include "journald-server.h"
int server_open_stdout_socket(Server *s);
int server_restore_streams(Server *s, FDSet *fds);
+
void stdout_stream_free(StdoutStream *s);
+void stdout_stream_send_notify(StdoutStream *s);
diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c
index 7e9ba12560..f3ac1a7ae0 100644
--- a/src/journal/journald-syslog.c
+++ b/src/journal/journald-syslog.c
@@ -25,8 +25,10 @@
#include "sd-messages.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "formats-util.h"
+#include "io-util.h"
#include "journald-console.h"
#include "journald-kmsg.h"
#include "journald-server.h"
@@ -35,7 +37,9 @@
#include "process-util.h"
#include "selinux-util.h"
#include "socket-util.h"
+#include "stdio-util.h"
#include "string-util.h"
+#include "syslog-util.h"
/* Warn once every 30s if we missed syslog message */
#define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC)
diff --git a/src/journal/journald-wall.c b/src/journal/journald-wall.c
index 5284914941..69540f1141 100644
--- a/src/journal/journald-wall.c
+++ b/src/journal/journald-wall.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "formats-util.h"
#include "journald-server.h"
#include "process-util.h"
diff --git a/src/journal/journald.c b/src/journal/journald.c
index 83236ceba9..b137e3c7be 100644
--- a/src/journal/journald.c
+++ b/src/journal/journald.c
@@ -61,10 +61,6 @@ int main(int argc, char *argv[]) {
log_debug("systemd-journald running as pid "PID_FMT, getpid());
server_driver_message(&server, SD_MESSAGE_JOURNAL_START, "Journal started");
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
-
for (;;) {
usec_t t = USEC_INFINITY, n;
@@ -117,10 +113,6 @@ int main(int argc, char *argv[]) {
server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP, "Journal stopped");
finish:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
-
server_done(&server);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c
index 22f75540b8..3cb1dfa986 100644
--- a/src/journal/mmap-cache.c
+++ b/src/journal/mmap-cache.c
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <sys/mman.h>
+#include "alloc-util.h"
#include "hashmap.h"
#include "list.h"
#include "log.h"
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index 9dcfc726ea..218df8cebe 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -30,11 +30,14 @@
#include "sd-journal.h"
+#include "alloc-util.h"
#include "catalog.h"
#include "compress.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "hostname-util.h"
#include "io-util.h"
@@ -46,6 +49,8 @@
#include "missing.h"
#include "path-util.h"
#include "replace-var.h"
+#include "stat-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
@@ -1020,8 +1025,6 @@ _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
_public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
int r;
- const char *word, *state;
- size_t l;
Object *o;
assert_return(j, -EINVAL);
@@ -1035,20 +1038,23 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
if (r < 0)
return r;
- FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) {
+ for(;;) {
_cleanup_free_ char *item = NULL;
- sd_id128_t id;
unsigned long long ll;
+ sd_id128_t id;
int k = 0;
- if (l < 2 || word[1] != '=')
- return -EINVAL;
+ r = extract_first_word(&cursor, &item, ";", EXTRACT_DONT_COALESCE_SEPARATORS);
+ if (r < 0)
+ return r;
- item = strndup(word, l);
- if (!item)
- return -ENOMEM;
+ if (r == 0)
+ break;
- switch (word[0]) {
+ if (strlen(item) < 2 || item[1] != '=')
+ return -EINVAL;
+
+ switch (item[0]) {
case 's':
k = sd_id128_from_string(item+2, &id);
diff --git a/src/journal/stacktrace.c b/src/journal/stacktrace.c
index e32550d644..4305462f80 100644
--- a/src/journal/stacktrace.c
+++ b/src/journal/stacktrace.c
@@ -22,6 +22,7 @@
#include <dwarf.h>
#include <elfutils/libdwfl.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "formats-util.h"
#include "macro.h"
diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c
index 72c1f60f02..aea8fd15e6 100644
--- a/src/journal/test-catalog.c
+++ b/src/journal/test-catalog.c
@@ -27,8 +27,10 @@
#include "sd-messages.h"
+#include "alloc-util.h"
#include "catalog.h"
#include "fd-util.h"
+#include "fileio.h"
#include "log.h"
#include "macro.h"
#include "string-util.h"
diff --git a/src/journal/test-compress-benchmark.c b/src/journal/test-compress-benchmark.c
index 0a9ab7f52c..93ea9c6318 100644
--- a/src/journal/test-compress-benchmark.c
+++ b/src/journal/test-compress-benchmark.c
@@ -19,8 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "compress.h"
#include "macro.h"
+#include "parse-util.h"
#include "random-util.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c
index e562fa1948..b9d90a8988 100644
--- a/src/journal/test-compress.c
+++ b/src/journal/test-compress.c
@@ -17,8 +17,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "compress.h"
#include "fd-util.h"
+#include "fileio.h"
#include "macro.h"
#include "random-util.h"
#include "util.h"
diff --git a/src/journal/test-journal-flush.c b/src/journal/test-journal-flush.c
index 6061623ae7..03d1522e23 100644
--- a/src/journal/test-journal-flush.c
+++ b/src/journal/test-journal-flush.c
@@ -23,6 +23,7 @@
#include "sd-journal.h"
+#include "alloc-util.h"
#include "journal-file.h"
#include "journal-internal.h"
#include "macro.h"
diff --git a/src/journal/test-journal-init.c b/src/journal/test-journal-init.c
index 717b703d19..142da85041 100644
--- a/src/journal/test-journal-init.c
+++ b/src/journal/test-journal-init.c
@@ -22,6 +22,7 @@
#include "sd-journal.h"
#include "log.h"
+#include "parse-util.h"
#include "rm-rf.h"
#include "util.h"
diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c
index 8069339c1f..4ad89fe4b6 100644
--- a/src/journal/test-journal-interleaving.c
+++ b/src/journal/test-journal-interleaving.c
@@ -24,11 +24,14 @@
#include <fcntl.h>
#include "sd-journal.h"
+
+#include "alloc-util.h"
#include "journal-file.h"
#include "journal-vacuum.h"
-#include "util.h"
#include "log.h"
+#include "parse-util.h"
#include "rm-rf.h"
+#include "util.h"
/* This program tests skipping around in a multi-file journal.
*/
diff --git a/src/journal/test-journal-match.c b/src/journal/test-journal-match.c
index 476477055a..abefedb992 100644
--- a/src/journal/test-journal-match.c
+++ b/src/journal/test-journal-match.c
@@ -23,6 +23,7 @@
#include "sd-journal.h"
+#include "alloc-util.h"
#include "journal-internal.h"
#include "log.h"
#include "string-util.h"
diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c
index b5ecf2f375..0cbef4b8c5 100644
--- a/src/journal/test-journal-stream.c
+++ b/src/journal/test-journal-stream.c
@@ -19,16 +19,19 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
#include <fcntl.h>
+#include <unistd.h>
#include "sd-journal.h"
-#include "util.h"
+
+#include "alloc-util.h"
+#include "journal-file.h"
+#include "journal-internal.h"
#include "log.h"
#include "macro.h"
+#include "parse-util.h"
#include "rm-rf.h"
-#include "journal-file.h"
-#include "journal-internal.h"
+#include "util.h"
#define N_ENTRIES 200
diff --git a/src/journal/test-journal-syslog.c b/src/journal/test-journal-syslog.c
index de942c50cc..1784187fe9 100644
--- a/src/journal/test-journal-syslog.c
+++ b/src/journal/test-journal-syslog.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "journald-syslog.h"
#include "macro.h"
#include "string-util.h"
diff --git a/src/journal/test-mmap-cache.c b/src/journal/test-mmap-cache.c
index ac1239acc4..fdd48e531c 100644
--- a/src/journal/test-mmap-cache.c
+++ b/src/journal/test-mmap-cache.c
@@ -19,12 +19,13 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
-#include <fcntl.h>
#include "fd-util.h"
+#include "fileio.h"
#include "macro.h"
#include "mmap-cache.h"
#include "util.h"
diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c
index f41bebced0..076bb2dac0 100644
--- a/src/libsystemd-network/dhcp6-option.c
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -23,14 +23,14 @@
#include <errno.h>
#include <string.h>
-#include "sparse-endian.h"
-#include "unaligned.h"
-#include "util.h"
-#include "strv.h"
-
+#include "alloc-util.h"
#include "dhcp6-internal.h"
#include "dhcp6-protocol.h"
#include "dns-domain.h"
+#include "sparse-endian.h"
+#include "strv.h"
+#include "unaligned.h"
+#include "util.h"
#define DHCP6_OPTION_IA_NA_LEN 12
#define DHCP6_OPTION_IA_TA_LEN 4
diff --git a/src/libsystemd-network/lldp-internal.c b/src/libsystemd-network/lldp-internal.c
index 70061e914f..583be2f55d 100644
--- a/src/libsystemd-network/lldp-internal.c
+++ b/src/libsystemd-network/lldp-internal.c
@@ -22,6 +22,7 @@
#include "sd-lldp.h"
+#include "alloc-util.h"
#include "lldp-internal.h"
/* We store maximum 1K chassis entries */
diff --git a/src/libsystemd-network/lldp-port.c b/src/libsystemd-network/lldp-port.c
index 7486b4c38f..97b6b485d2 100644
--- a/src/libsystemd-network/lldp-port.c
+++ b/src/libsystemd-network/lldp-port.c
@@ -20,6 +20,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "async.h"
#include "lldp-port.h"
#include "lldp-network.h"
diff --git a/src/libsystemd-network/lldp-tlv.c b/src/libsystemd-network/lldp-tlv.c
index 66af22e37d..0851957ab4 100644
--- a/src/libsystemd-network/lldp-tlv.c
+++ b/src/libsystemd-network/lldp-tlv.c
@@ -23,8 +23,9 @@
#include <net/ethernet.h>
#include <arpa/inet.h>
-#include "macro.h"
+#include "alloc-util.h"
#include "lldp-tlv.h"
+#include "macro.h"
int tlv_section_new(tlv_section **ret) {
tlv_section *s;
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 39551b5761..52d76e443e 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -25,16 +25,19 @@
#include "sd-ndisc.h"
+#include "alloc-util.h"
#include "condition.h"
#include "conf-parser.h"
#include "dhcp-lease-internal.h"
#include "log.h"
+#include "network-internal.h"
+#include "hexdecoct.h"
+#include "parse-util.h"
#include "siphash24.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
#include "util.h"
-#include "network-internal.h"
const char *net_get_name(struct udev_device *device) {
const char *name, *field;
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index a6d6a176e4..57fc8216c3 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -28,6 +28,7 @@
#include "sd-dhcp-client.h"
+#include "alloc-util.h"
#include "async.h"
#include "dhcp-identifier.h"
#include "dhcp-internal.h"
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index d982936a28..c850538d74 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -26,6 +26,7 @@
#include "sd-dhcp-lease.h"
+#include "alloc-util.h"
#include "dhcp-lease-internal.h"
#include "dhcp-protocol.h"
#include "dns-domain.h"
@@ -34,6 +35,8 @@
#include "hostname-util.h"
#include "in-addr-util.h"
#include "network-internal.h"
+#include "hexdecoct.h"
+#include "parse-util.h"
#include "unaligned.h"
int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index a2a8c16fc8..8d0d9955c3 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -24,6 +24,7 @@
#include "sd-dhcp-server.h"
+#include "alloc-util.h"
#include "dhcp-internal.h"
#include "dhcp-server-internal.h"
#include "fd-util.h"
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index ade1b470d4..e29de60d24 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -26,6 +26,7 @@
#include "sd-dhcp6-client.h"
+#include "alloc-util.h"
#include "dhcp-identifier.h"
#include "dhcp6-internal.h"
#include "dhcp6-lease-internal.h"
@@ -33,6 +34,7 @@
#include "fd-util.h"
#include "network-internal.h"
#include "random-util.h"
+#include "string-table.h"
#include "util.h"
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c
index f34af6eaba..3f32ba35e7 100644
--- a/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -22,11 +22,11 @@
#include <errno.h>
-#include "strv.h"
-#include "util.h"
-
+#include "alloc-util.h"
#include "dhcp6-lease-internal.h"
#include "dhcp6-protocol.h"
+#include "strv.h"
+#include "util.h"
int dhcp6_lease_clear_timers(DHCP6IA *ia) {
assert_return(ia, -EINVAL);
diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c
index 3053724ea2..5340fdc0c1 100644
--- a/src/libsystemd-network/sd-ipv4acd.c
+++ b/src/libsystemd-network/sd-ipv4acd.c
@@ -26,6 +26,7 @@
#include "sd-ipv4acd.h"
+#include "alloc-util.h"
#include "arp-util.h"
#include "event-util.h"
#include "fd-util.h"
diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c
index 68ec58da90..0d915e20e7 100644
--- a/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/libsystemd-network/sd-ipv4ll.c
@@ -27,6 +27,7 @@
#include "sd-ipv4acd.h"
#include "sd-ipv4ll.h"
+#include "alloc-util.h"
#include "event-util.h"
#include "in-addr-util.h"
#include "list.h"
diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
index b2b85e56e8..4ebe8053fa 100644
--- a/src/libsystemd-network/sd-lldp.c
+++ b/src/libsystemd-network/sd-lldp.c
@@ -24,7 +24,9 @@
#include "sd-lldp.h"
+#include "alloc-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "hashmap.h"
#include "lldp-internal.h"
#include "lldp-port.h"
diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c
index ca4bb6325b..c494b9d6d8 100644
--- a/src/libsystemd-network/sd-ndisc.c
+++ b/src/libsystemd-network/sd-ndisc.c
@@ -26,6 +26,7 @@
#include "sd-ndisc.h"
+#include "alloc-util.h"
#include "async.h"
#include "icmp6-util.h"
#include "list.h"
diff --git a/src/libsystemd-network/sd-pppoe.c b/src/libsystemd-network/sd-pppoe.c
index 03a88973bf..045decc46c 100644
--- a/src/libsystemd-network/sd-pppoe.c
+++ b/src/libsystemd-network/sd-pppoe.c
@@ -30,6 +30,7 @@
#include "sd-pppoe.h"
+#include "alloc-util.h"
#include "async.h"
#include "event-util.h"
#include "fd-util.h"
diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
index 40a85eb25e..5b52c1cbb9 100644
--- a/src/libsystemd-network/test-dhcp-client.c
+++ b/src/libsystemd-network/test-dhcp-client.c
@@ -27,6 +27,7 @@
#include "sd-dhcp-client.h"
#include "sd-event.h"
+#include "alloc-util.h"
#include "dhcp-identifier.h"
#include "dhcp-internal.h"
#include "dhcp-protocol.h"
diff --git a/src/libsystemd-network/test-dhcp-option.c b/src/libsystemd-network/test-dhcp-option.c
index b1ef174849..2d29e28f16 100644
--- a/src/libsystemd-network/test-dhcp-option.c
+++ b/src/libsystemd-network/test-dhcp-option.c
@@ -5,11 +5,11 @@
#include <errno.h>
#include <string.h>
-#include "util.h"
-#include "macro.h"
-
-#include "dhcp-protocol.h"
+#include "alloc-util.h"
#include "dhcp-internal.h"
+#include "dhcp-protocol.h"
+#include "macro.h"
+#include "util.h"
struct option_desc {
uint8_t sname[64];
diff --git a/src/libsystemd-network/test-ipv4ll-manual.c b/src/libsystemd-network/test-ipv4ll-manual.c
index 08421c3575..913a929069 100644
--- a/src/libsystemd-network/test-ipv4ll-manual.c
+++ b/src/libsystemd-network/test-ipv4ll-manual.c
@@ -29,9 +29,11 @@
#include "sd-ipv4ll.h"
#include "sd-netlink.h"
+#include "alloc-util.h"
#include "event-util.h"
#include "in-addr-util.h"
#include "netlink-util.h"
+#include "parse-util.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/libsystemd-network/test-lldp.c b/src/libsystemd-network/test-lldp.c
index 109462662f..931df7c170 100644
--- a/src/libsystemd-network/test-lldp.c
+++ b/src/libsystemd-network/test-lldp.c
@@ -28,6 +28,7 @@
#include "sd-event.h"
#include "sd-lldp.h"
+#include "alloc-util.h"
#include "event-util.h"
#include "fd-util.h"
#include "lldp-network.h"
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index e68207ae07..d5bc32e757 100644
--- a/src/libsystemd/sd-bus/bus-control.c
+++ b/src/libsystemd/sd-bus/bus-control.c
@@ -28,14 +28,17 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-bloom.h"
+#include "bus-control.h"
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-util.h"
-#include "capability.h"
+#include "capability-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
-#include "bus-control.h"
+#include "user-util.h"
_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
int r;
diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c
index d7bff784b8..2922da3763 100644
--- a/src/libsystemd/sd-bus/bus-creds.c
+++ b/src/libsystemd/sd-bus/bus-creds.c
@@ -22,20 +22,24 @@
#include <linux/capability.h>
#include <stdlib.h>
-#include "audit.h"
+#include "alloc-util.h"
+#include "audit-util.h"
#include "bus-creds.h"
#include "bus-label.h"
#include "bus-message.h"
#include "bus-util.h"
-#include "capability.h"
+#include "capability-util.h"
#include "cgroup-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
+#include "hexdecoct.h"
+#include "parse-util.h"
#include "process-util.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
+#include "user-util.h"
#include "util.h"
enum {
diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c
index cd7fcc7c80..43a7e67a6d 100644
--- a/src/libsystemd/sd-bus/bus-dump.c
+++ b/src/libsystemd/sd-bus/bus-dump.c
@@ -19,18 +19,21 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
+#include "bus-dump.h"
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-type.h"
#include "cap-list.h"
-#include "capability.h"
+#include "capability-util.h"
+#include "fileio.h"
#include "formats-util.h"
+#include "locale-util.h"
#include "macro.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "util.h"
-#include "bus-dump.h"
static char *indent(unsigned level, unsigned flags) {
char *p;
diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c
index 831ceb86b9..84229c2964 100644
--- a/src/libsystemd/sd-bus/bus-error.c
+++ b/src/libsystemd/sd-bus/bus-error.c
@@ -28,6 +28,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "errno-list.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/libsystemd/sd-bus/bus-internal.c b/src/libsystemd/sd-bus/bus-internal.c
index 486a8cf8de..d9f9cd1c5e 100644
--- a/src/libsystemd/sd-bus/bus-internal.c
+++ b/src/libsystemd/sd-bus/bus-internal.c
@@ -19,8 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-message.h"
+#include "hexdecoct.h"
#include "string-util.h"
bool object_path_is_valid(const char *p) {
diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c
index f5a8885332..a90536bac9 100644
--- a/src/libsystemd/sd-bus/bus-introspect.c
+++ b/src/libsystemd/sd-bus/bus-introspect.c
@@ -24,6 +24,7 @@
#include "bus-protocol.h"
#include "bus-signature.h"
#include "fd-util.h"
+#include "fileio.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index f311e86d44..6716f6daca 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -34,19 +34,22 @@
#include <libgen.h>
#undef basename
+#include "alloc-util.h"
#include "bus-bloom.h"
#include "bus-internal.h"
#include "bus-kernel.h"
#include "bus-label.h"
#include "bus-message.h"
#include "bus-util.h"
-#include "capability.h"
+#include "capability-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
#include "memfd-util.h"
+#include "parse-util.h"
#include "string-util.h"
#include "strv.h"
+#include "user-util.h"
#include "util.h"
#define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c
index 58b19fbdc7..55dc7caa53 100644
--- a/src/libsystemd/sd-bus/bus-match.c
+++ b/src/libsystemd/sd-bus/bus-match.c
@@ -19,11 +19,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-match.h"
#include "bus-message.h"
#include "bus-util.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "hexdecoct.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
index 447e25db8a..5c80095bf0 100644
--- a/src/libsystemd/sd-bus/bus-message.c
+++ b/src/libsystemd/sd-bus/bus-message.c
@@ -25,6 +25,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-gvariant.h"
#include "bus-internal.h"
#include "bus-message.h"
@@ -32,6 +33,7 @@
#include "bus-type.h"
#include "bus-util.h"
#include "fd-util.h"
+#include "io-util.h"
#include "memfd-util.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index d3679800b5..8c472626a8 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-introspect.h"
#include "bus-message.h"
diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c
index 63f10eba2c..550bad27ba 100644
--- a/src/libsystemd/sd-bus/bus-slot.c
+++ b/src/libsystemd/sd-bus/bus-slot.c
@@ -21,6 +21,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-control.h"
#include "bus-objects.h"
#include "string-util.h"
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 42d7f80461..a5cb667630 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -27,14 +27,17 @@
#include "sd-bus.h"
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-socket.h"
#include "fd-util.h"
#include "formats-util.h"
+#include "hexdecoct.h"
#include "macro.h"
#include "missing.h"
#include "signal-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "user-util.h"
#include "utf8.h"
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
index 0911156e19..fd7e58fcfa 100644
--- a/src/libsystemd/sd-bus/bus-track.c
+++ b/src/libsystemd/sd-bus/bus-track.c
@@ -21,6 +21,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-track.h"
#include "bus-util.h"
diff --git a/src/libsystemd/sd-bus/busctl-introspect.c b/src/libsystemd/sd-bus/busctl-introspect.c
index 5604db9716..71f962b00c 100644
--- a/src/libsystemd/sd-bus/busctl-introspect.c
+++ b/src/libsystemd/sd-bus/busctl-introspect.c
@@ -21,10 +21,11 @@
#include "sd-bus.h"
+#include "alloc-util.h"
+#include "busctl-introspect.h"
#include "string-util.h"
#include "util.h"
#include "xml.h"
-#include "busctl-introspect.h"
#define NODE_DEPTH_MAX 16
diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c
index d3e846db84..452ac7c407 100644
--- a/src/libsystemd/sd-bus/busctl.c
+++ b/src/libsystemd/sd-bus/busctl.c
@@ -23,6 +23,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-dump.h"
#include "bus-internal.h"
#include "bus-signature.h"
@@ -31,8 +32,10 @@
#include "busctl-introspect.h"
#include "escape.h"
#include "fd-util.h"
+#include "locale-util.h"
#include "log.h"
#include "pager.h"
+#include "parse-util.h"
#include "path-util.h"
#include "set.h"
#include "strv.h"
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 7b91c2583d..a8d79b01b0 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -29,6 +29,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-container.h"
#include "bus-control.h"
#include "bus-internal.h"
@@ -48,6 +49,8 @@
#include "hostname-util.h"
#include "macro.h"
#include "missing.h"
+#include "hexdecoct.h"
+#include "parse-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
diff --git a/src/libsystemd/sd-bus/test-bus-benchmark.c b/src/libsystemd/sd-bus/test-bus-benchmark.c
index 549c88cd2d..96a0929a14 100644
--- a/src/libsystemd/sd-bus/test-bus-benchmark.c
+++ b/src/libsystemd/sd-bus/test-bus-benchmark.c
@@ -23,6 +23,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-internal.h"
#include "bus-kernel.h"
#include "bus-util.h"
diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c
index e9e5e4a8e3..767aef63ff 100644
--- a/src/libsystemd/sd-bus/test-bus-chat.c
+++ b/src/libsystemd/sd-bus/test-bus-chat.c
@@ -26,6 +26,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-internal.h"
#include "bus-match.h"
diff --git a/src/libsystemd/sd-bus/test-bus-gvariant.c b/src/libsystemd/sd-bus/test-bus-gvariant.c
index f94da4cccd..931c001788 100644
--- a/src/libsystemd/sd-bus/test-bus-gvariant.c
+++ b/src/libsystemd/sd-bus/test-bus-gvariant.c
@@ -25,6 +25,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-dump.h"
#include "bus-gvariant.h"
#include "bus-internal.h"
diff --git a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
index ff7f9cdafa..dbdaa69fbe 100644
--- a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
+++ b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
@@ -21,6 +21,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-kernel.h"
#include "bus-util.h"
#include "fd-util.h"
diff --git a/src/libsystemd/sd-bus/test-bus-kernel.c b/src/libsystemd/sd-bus/test-bus-kernel.c
index 7d05953cd0..0080f71d3b 100644
--- a/src/libsystemd/sd-bus/test-bus-kernel.c
+++ b/src/libsystemd/sd-bus/test-bus-kernel.c
@@ -23,6 +23,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-dump.h"
#include "bus-kernel.h"
#include "bus-util.h"
diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c
index c0daa451ec..0747d6a37c 100644
--- a/src/libsystemd/sd-bus/test-bus-marshal.c
+++ b/src/libsystemd/sd-bus/test-bus-marshal.c
@@ -32,12 +32,14 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-dump.h"
#include "bus-label.h"
#include "bus-message.h"
#include "bus-util.h"
#include "fd-util.h"
#include "log.h"
+#include "hexdecoct.h"
#include "util.h"
static void test_bus_path_encode_unique(void) {
diff --git a/src/libsystemd/sd-bus/test-bus-objects.c b/src/libsystemd/sd-bus/test-bus-objects.c
index 138db910ea..5bc72e2355 100644
--- a/src/libsystemd/sd-bus/test-bus-objects.c
+++ b/src/libsystemd/sd-bus/test-bus-objects.c
@@ -24,6 +24,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-dump.h"
#include "bus-internal.h"
#include "bus-message.h"
diff --git a/src/libsystemd/sd-bus/test-bus-proxy.c b/src/libsystemd/sd-bus/test-bus-proxy.c
index ae04ff5b0d..428e185769 100644
--- a/src/libsystemd/sd-bus/test-bus-proxy.c
+++ b/src/libsystemd/sd-bus/test-bus-proxy.c
@@ -25,6 +25,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-dump.h"
#include "bus-kernel.h"
#include "bus-util.h"
diff --git a/src/libsystemd/sd-bus/test-bus-zero-copy.c b/src/libsystemd/sd-bus/test-bus-zero-copy.c
index 1be0dbcd82..ff8df61a9e 100644
--- a/src/libsystemd/sd-bus/test-bus-zero-copy.c
+++ b/src/libsystemd/sd-bus/test-bus-zero-copy.c
@@ -23,6 +23,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-dump.h"
#include "bus-kernel.h"
#include "bus-message.h"
diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c
index 85c73722df..27045e25d0 100644
--- a/src/libsystemd/sd-daemon/sd-daemon.c
+++ b/src/libsystemd/sd-daemon/sd-daemon.c
@@ -35,12 +35,17 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "fd-util.h"
+#include "fs-util.h"
+#include "parse-util.h"
#include "path-util.h"
#include "socket-util.h"
#include "strv.h"
#include "util.h"
+#define SNDBUF_SIZE (8*1024*1024)
+
static void unsetenv_all(bool unset_environment) {
if (!unset_environment)
@@ -431,12 +436,19 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
goto finish;
}
+ if (strlen(e) > sizeof(sockaddr.un.sun_path)) {
+ r = -EINVAL;
+ goto finish;
+ }
+
fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
if (fd < 0) {
r = -errno;
goto finish;
}
+ fd_inc_sndbuf(fd, SNDBUF_SIZE);
+
iovec.iov_len = strlen(state);
strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c
index c98053220c..ae3157ee5e 100644
--- a/src/libsystemd/sd-device/device-enumerator.c
+++ b/src/libsystemd/sd-device/device-enumerator.c
@@ -20,8 +20,10 @@
#include "sd-device.h"
+#include "alloc-util.h"
#include "device-enumerator-private.h"
#include "device-util.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "prioq.h"
#include "set.h"
diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c
index bcabf9468d..a13477e753 100644
--- a/src/libsystemd/sd-device/device-private.c
+++ b/src/libsystemd/sd-device/device-private.c
@@ -24,20 +24,25 @@
#include "sd-device.h"
+#include "alloc-util.h"
#include "device-internal.h"
#include "device-private.h"
#include "device-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "macro.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "path-util.h"
#include "refcnt.h"
#include "set.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "strxcpyx.h"
+#include "user-util.h"
#include "util.h"
int device_add_property(sd_device *device, const char *key, const char *value) {
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index 593dda52f2..0d40bc5c00 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -24,15 +24,19 @@
#include "sd-device.h"
+#include "alloc-util.h"
#include "device-internal.h"
#include "device-private.h"
#include "device-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "macro.h"
+#include "parse-util.h"
#include "path-util.h"
#include "set.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "strxcpyx.h"
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index b3f8881714..ee4886700e 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -27,6 +27,7 @@
#include "sd-event.h"
#include "sd-id128.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "hashmap.h"
#include "list.h"
diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c
index 9304fd376e..0e034863d6 100644
--- a/src/libsystemd/sd-hwdb/sd-hwdb.c
+++ b/src/libsystemd/sd-hwdb/sd-hwdb.c
@@ -29,6 +29,7 @@
#include "sd-hwdb.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "hashmap.h"
#include "hwdb-internal.h"
diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c
index 335ad3b1b4..1e17ea6a06 100644
--- a/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/libsystemd/sd-id128/sd-id128.c
@@ -28,6 +28,7 @@
#include "fd-util.h"
#include "io-util.h"
#include "macro.h"
+#include "hexdecoct.h"
#include "random-util.h"
#include "util.h"
diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c
index f564d43e06..cd766c3f91 100644
--- a/src/libsystemd/sd-login/sd-login.c
+++ b/src/libsystemd/sd-login/sd-login.c
@@ -27,15 +27,20 @@
#include "sd-login.h"
+#include "alloc-util.h"
#include "cgroup-util.h"
+#include "dirent-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "hostname-util.h"
#include "io-util.h"
#include "login-util.h"
#include "macro.h"
+#include "parse-util.h"
+#include "path-util.h"
#include "socket-util.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c
index 46aa73b38a..b0f94c9522 100644
--- a/src/libsystemd/sd-login/test-login.c
+++ b/src/libsystemd/sd-login/test-login.c
@@ -24,6 +24,7 @@
#include "sd-login.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "formats-util.h"
#include "string-util.h"
diff --git a/src/libsystemd/sd-netlink/local-addresses.c b/src/libsystemd/sd-netlink/local-addresses.c
index e2f637f7f9..a00865b56b 100644
--- a/src/libsystemd/sd-netlink/local-addresses.c
+++ b/src/libsystemd/sd-netlink/local-addresses.c
@@ -21,6 +21,8 @@
***/
#include "sd-netlink.h"
+
+#include "alloc-util.h"
#include "netlink-util.h"
#include "macro.h"
#include "local-addresses.h"
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c
index 80ad70cfee..03971b3596 100644
--- a/src/libsystemd/sd-netlink/netlink-message.c
+++ b/src/libsystemd/sd-netlink/netlink-message.c
@@ -25,6 +25,7 @@
#include "sd-netlink.h"
+#include "alloc-util.h"
#include "formats-util.h"
#include "missing.h"
#include "netlink-internal.h"
diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c
index 68a4d3c0d1..13945202e4 100644
--- a/src/libsystemd/sd-netlink/netlink-socket.c
+++ b/src/libsystemd/sd-netlink/netlink-socket.c
@@ -25,6 +25,7 @@
#include "sd-netlink.h"
+#include "alloc-util.h"
#include "formats-util.h"
#include "missing.h"
#include "netlink-internal.h"
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index 4a5340e659..cf0a6248d6 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -28,16 +28,15 @@
#include <linux/if_bridge.h>
#include <linux/if_addr.h>
#include <linux/if.h>
-
#include <linux/ip.h>
#include <linux/if_link.h>
#include <linux/if_tunnel.h>
#include "macro.h"
-#include "util.h"
-
-#include "netlink-types.h"
#include "missing.h"
+#include "netlink-types.h"
+#include "string-table.h"
+#include "util.h"
/* Maximum ARP IP target defined in kernel */
#define BOND_MAX_ARP_TARGETS 16
diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c
index ba1f2a5a42..7c24e053cf 100644
--- a/src/libsystemd/sd-netlink/sd-netlink.c
+++ b/src/libsystemd/sd-netlink/sd-netlink.c
@@ -24,6 +24,7 @@
#include "sd-netlink.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "hashmap.h"
#include "macro.h"
diff --git a/src/libsystemd/sd-netlink/test-local-addresses.c b/src/libsystemd/sd-netlink/test-local-addresses.c
index 9867eec065..7180175970 100644
--- a/src/libsystemd/sd-netlink/test-local-addresses.c
+++ b/src/libsystemd/sd-netlink/test-local-addresses.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "in-addr-util.h"
#include "local-addresses.h"
#include "af-list.h"
diff --git a/src/libsystemd/sd-network/network-util.c b/src/libsystemd/sd-network/network-util.c
index 8070ff07c4..a2d6c59314 100644
--- a/src/libsystemd/sd-network/network-util.c
+++ b/src/libsystemd/sd-network/network-util.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "fd-util.h"
#include "network-util.h"
#include "strv.h"
diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c
index ad1227264c..efbceba83d 100644
--- a/src/libsystemd/sd-network/sd-network.c
+++ b/src/libsystemd/sd-network/sd-network.c
@@ -27,12 +27,15 @@
#include "sd-network.h"
+#include "alloc-util.h"
+#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "macro.h"
+#include "parse-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
-#include "fd-util.h"
_public_ int sd_network_get_operational_state(char **state) {
_cleanup_free_ char *s = NULL;
diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c
index 8e3eeb15d8..480f1ad065 100644
--- a/src/libsystemd/sd-path/sd-path.c
+++ b/src/libsystemd/sd-path/sd-path.c
@@ -19,8 +19,10 @@
#include "sd-path.h"
+#include "alloc-util.h"
#include "architecture.h"
#include "fd-util.h"
+#include "fileio.h"
#include "missing.h"
#include "path-util.h"
#include "string-util.h"
diff --git a/src/libsystemd/sd-resolve/sd-resolve.c b/src/libsystemd/sd-resolve/sd-resolve.c
index 724405d534..48767600c9 100644
--- a/src/libsystemd/sd-resolve/sd-resolve.c
+++ b/src/libsystemd/sd-resolve/sd-resolve.c
@@ -33,6 +33,7 @@
#include "sd-resolve.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "io-util.h"
#include "list.h"
diff --git a/src/libsystemd/sd-resolve/test-resolve.c b/src/libsystemd/sd-resolve/test-resolve.c
index 87e6e47041..05544a584c 100644
--- a/src/libsystemd/sd-resolve/test-resolve.c
+++ b/src/libsystemd/sd-resolve/test-resolve.c
@@ -30,6 +30,7 @@
#include "sd-resolve.h"
+#include "alloc-util.h"
#include "macro.h"
#include "resolve-util.h"
#include "socket-util.h"
diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c
index 1e513f3ff7..814e016800 100644
--- a/src/libudev/libudev-device.c
+++ b/src/libudev/libudev-device.c
@@ -37,10 +37,12 @@
#include "libudev.h"
#include "sd-device.h"
+#include "alloc-util.h"
#include "device-private.h"
#include "device-util.h"
#include "libudev-device-internal.h"
#include "libudev-private.h"
+#include "parse-util.h"
/**
* SECTION:libudev-device
diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c
index 56436772b0..442f9615f2 100644
--- a/src/libudev/libudev-enumerate.c
+++ b/src/libudev/libudev-enumerate.c
@@ -31,6 +31,7 @@
#include "libudev.h"
#include "sd-device.h"
+#include "alloc-util.h"
#include "device-enumerator-private.h"
#include "device-util.h"
#include "libudev-device-internal.h"
diff --git a/src/libudev/libudev-hwdb.c b/src/libudev/libudev-hwdb.c
index 6dc2b0533e..eba698d163 100644
--- a/src/libudev/libudev-hwdb.c
+++ b/src/libudev/libudev-hwdb.c
@@ -19,6 +19,7 @@
#include "sd-hwdb.h"
+#include "alloc-util.h"
#include "hwdb-util.h"
#include "libudev-private.h"
diff --git a/src/libudev/libudev-list.c b/src/libudev/libudev-list.c
index 19e9130be0..da496ed456 100644
--- a/src/libudev/libudev-list.c
+++ b/src/libudev/libudev-list.c
@@ -17,11 +17,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
-#include <stddef.h>
#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
#include <string.h>
+#include "alloc-util.h"
#include "libudev-private.h"
/**
diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c
index 5590aec2b7..c3883e485b 100644
--- a/src/libudev/libudev-monitor.c
+++ b/src/libudev/libudev-monitor.c
@@ -30,10 +30,13 @@
#include "libudev.h"
+#include "alloc-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "formats-util.h"
#include "libudev-private.h"
#include "missing.h"
+#include "mount-util.h"
#include "socket-util.h"
#include "string-util.h"
diff --git a/src/libudev/libudev-queue.c b/src/libudev/libudev-queue.c
index a22994c8a2..58410b1b8f 100644
--- a/src/libudev/libudev-queue.c
+++ b/src/libudev/libudev-queue.c
@@ -24,6 +24,7 @@
#include <errno.h>
#include <sys/inotify.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "io-util.h"
#include "libudev-private.h"
diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c
index a614230df4..574cfeac85 100644
--- a/src/libudev/libudev-util.c
+++ b/src/libudev/libudev-util.c
@@ -29,6 +29,7 @@
#include "MurmurHash2.h"
#include "device-nodes.h"
#include "libudev-private.h"
+#include "syslog-util.h"
#include "utf8.h"
/**
diff --git a/src/libudev/libudev.c b/src/libudev/libudev.c
index afadfe6993..63fb05547d 100644
--- a/src/libudev/libudev.c
+++ b/src/libudev/libudev.c
@@ -26,6 +26,7 @@
#include "libudev.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "libudev-private.h"
#include "missing.h"
diff --git a/src/locale/localed.c b/src/locale/localed.c
index 73e25f0642..720cbbaaba 100644
--- a/src/locale/localed.c
+++ b/src/locale/localed.c
@@ -30,20 +30,23 @@
#include "sd-bus.h"
-#include "util.h"
-#include "mkdir.h"
-#include "strv.h"
-#include "def.h"
-#include "env-util.h"
-#include "fileio.h"
-#include "fileio-label.h"
-#include "bus-util.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-message.h"
+#include "bus-util.h"
+#include "def.h"
+#include "env-util.h"
#include "event-util.h"
+#include "fd-util.h"
+#include "fileio-label.h"
+#include "fileio.h"
#include "locale-util.h"
+#include "mkdir.h"
+#include "path-util.h"
#include "selinux-util.h"
-#include "fd-util.h"
+#include "strv.h"
+#include "user-util.h"
+#include "util.h"
enum {
/* We don't list LC_ALL here on purpose. People should be
diff --git a/src/login/inhibit.c b/src/login/inhibit.c
index f79f89af7e..70fef332f7 100644
--- a/src/login/inhibit.c
+++ b/src/login/inhibit.c
@@ -27,6 +27,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "fd-util.h"
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 1cd186dec3..aff68a49fe 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -27,6 +27,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "cgroup-show.h"
@@ -35,6 +36,7 @@
#include "logs-show.h"
#include "macro.h"
#include "pager.h"
+#include "parse-util.h"
#include "process-util.h"
#include "signal-util.h"
#include "spawn-polkit-agent.h"
diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c
index 4d7bda3ee0..d0dd569a03 100644
--- a/src/login/logind-acl.c
+++ b/src/login/logind-acl.c
@@ -23,6 +23,8 @@
#include <string.h>
#include "acl-util.h"
+#include "alloc-util.h"
+#include "dirent-util.h"
#include "escape.h"
#include "fd-util.h"
#include "formats-util.h"
diff --git a/src/login/logind-action.c b/src/login/logind-action.c
index f06f8edc07..185108f8f1 100644
--- a/src/login/logind-action.c
+++ b/src/login/logind-action.c
@@ -21,14 +21,16 @@
#include <unistd.h>
-#include "conf-parser.h"
-#include "special.h"
-#include "sleep-config.h"
-#include "bus-util.h"
+#include "alloc-util.h"
#include "bus-error.h"
-#include "logind-action.h"
+#include "bus-util.h"
+#include "conf-parser.h"
#include "formats-util.h"
+#include "logind-action.h"
#include "process-util.h"
+#include "sleep-config.h"
+#include "special.h"
+#include "string-table.h"
#include "terminal-util.h"
#include "user-util.h"
diff --git a/src/login/logind-button.c b/src/login/logind-button.c
index b98035be21..b08b69dbfc 100644
--- a/src/login/logind-button.c
+++ b/src/login/logind-button.c
@@ -28,6 +28,7 @@
#include "sd-messages.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "logind-button.h"
#include "string-util.h"
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index c2541e490b..b3f30c8dc9 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -25,6 +25,7 @@
#include <pwd.h>
#include <linux/vt.h>
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "cgroup-util.h"
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 61c2c9ba40..7890d68aa0 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -26,15 +26,18 @@
#include "sd-messages.h"
-#include "audit.h"
+#include "alloc-util.h"
+#include "audit-util.h"
#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-util.h"
+#include "dirent-util.h"
#include "efivars.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio-label.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "logind.h"
#include "mkdir.h"
#include "path-util.h"
diff --git a/src/login/logind-device.c b/src/login/logind-device.c
index ee4c45fb8d..ffb9162e56 100644
--- a/src/login/logind-device.c
+++ b/src/login/logind-device.c
@@ -21,8 +21,9 @@
#include <string.h>
-#include "util.h"
+#include "alloc-util.h"
#include "logind-device.h"
+#include "util.h"
Device* device_new(Manager *m, const char *sysfs, bool master) {
Device *d;
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
index c4b74eb734..33fbdde557 100644
--- a/src/login/logind-inhibit.c
+++ b/src/login/logind-inhibit.c
@@ -24,12 +24,15 @@
#include <string.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
#include "logind-inhibit.h"
#include "mkdir.h"
+#include "parse-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "user-util.h"
#include "util.h"
diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
index 346e1d2cec..43b578f364 100644
--- a/src/login/logind-seat-dbus.c
+++ b/src/login/logind-seat-dbus.c
@@ -22,13 +22,15 @@
#include <errno.h>
#include <string.h>
-#include "util.h"
-#include "bus-util.h"
-#include "strv.h"
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-label.h"
-#include "logind.h"
+#include "bus-util.h"
#include "logind-seat.h"
+#include "logind.h"
+#include "strv.h"
+#include "user-util.h"
+#include "util.h"
static int property_get_active_session(
sd_bus *bus,
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index dad552d5f2..1f4936cebe 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -26,11 +26,14 @@
#include "sd-messages.h"
+#include "alloc-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "formats-util.h"
#include "logind-acl.h"
#include "logind-seat.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "string-util.h"
#include "terminal-util.h"
#include "util.h"
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index fe398a5eb6..7810199a54 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include <string.h>
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-label.h"
#include "bus-util.h"
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index 3a0bb720f9..9bf3ca0995 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -27,6 +27,7 @@
#include "libudev.h"
+#include "alloc-util.h"
#include "bus-util.h"
#include "fd-util.h"
#include "logind-session-device.h"
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 714b1cb299..a53dcb9960 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -30,7 +30,8 @@
#include "sd-messages.h"
-#include "audit.h"
+#include "alloc-util.h"
+#include "audit-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "escape.h"
@@ -41,7 +42,9 @@
#include "io-util.h"
#include "logind-session.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "string-table.h"
#include "terminal-util.h"
#include "user-util.h"
#include "util.h"
diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
index 5975b579e9..df901f6558 100644
--- a/src/login/logind-user-dbus.c
+++ b/src/login/logind-user-dbus.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include <string.h>
+#include "alloc-util.h"
#include "bus-util.h"
#include "formats-util.h"
#include "logind-user.h"
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 80328068cd..56bc5a010c 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -24,6 +24,7 @@
#include <sys/mount.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "clean-ipc.h"
@@ -32,15 +33,20 @@
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "label.h"
#include "logind-user.h"
#include "mkdir.h"
+#include "mount-util.h"
+#include "parse-util.h"
#include "path-util.h"
#include "rm-rf.h"
#include "smack-util.h"
#include "special.h"
+#include "string-table.h"
#include "unit-name.h"
+#include "user-util.h"
#include "util.h"
User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c
index 9c766bcb25..3e7a935a34 100644
--- a/src/login/logind-utmp.c
+++ b/src/login/logind-utmp.c
@@ -26,7 +26,8 @@
#include "sd-messages.h"
-#include "audit.h"
+#include "alloc-util.h"
+#include "audit-util.h"
#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-util.h"
diff --git a/src/login/logind.c b/src/login/logind.c
index 02c87ca58e..4b8c834269 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -27,9 +27,11 @@
#include "libudev.h"
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "conf-parser.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "formats-util.h"
#include "logind.h"
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index dbd055a79a..0d61f528db 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -30,7 +30,8 @@
#include <security/pam_modutil.h>
#include <sys/file.h>
-#include "audit.h"
+#include "alloc-util.h"
+#include "audit-util.h"
#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-util.h"
@@ -41,6 +42,7 @@
#include "hostname-util.h"
#include "login-util.h"
#include "macro.h"
+#include "parse-util.h"
#include "socket-util.h"
#include "strv.h"
#include "terminal-util.h"
diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c
index 32e53c0a11..e9ca4bb03d 100644
--- a/src/login/sysfs-show.c
+++ b/src/login/sysfs-show.c
@@ -24,6 +24,8 @@
#include "libudev.h"
+#include "alloc-util.h"
+#include "locale-util.h"
#include "path-util.h"
#include "string-util.h"
#include "sysfs-show.h"
diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c
index 2453a9ff04..4ec1766033 100644
--- a/src/machine/image-dbus.c
+++ b/src/machine/image-dbus.c
@@ -19,11 +19,13 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "bus-label.h"
-#include "strv.h"
#include "bus-util.h"
-#include "machine-image.h"
#include "image-dbus.h"
+#include "machine-image.h"
+#include "strv.h"
+#include "user-util.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, image_type, ImageType);
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index c17a98e90f..452130a29c 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -29,6 +29,7 @@
#include <libgen.h>
#undef basename
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-internal.h"
#include "bus-label.h"
@@ -38,6 +39,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "in-addr-util.h"
#include "local-addresses.h"
#include "machine-dbus.h"
@@ -47,6 +49,7 @@
#include "process-util.h"
#include "strv.h"
#include "terminal-util.h"
+#include "user-util.h"
static int property_get_id(
sd_bus *bus,
diff --git a/src/machine/machine.c b/src/machine/machine.c
index e41f8add98..ef5c8551b5 100644
--- a/src/machine/machine.c
+++ b/src/machine/machine.c
@@ -25,6 +25,7 @@
#include "sd-messages.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "escape.h"
@@ -35,10 +36,13 @@
#include "machine-dbus.h"
#include "machine.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "special.h"
+#include "string-table.h"
#include "terminal-util.h"
#include "unit-name.h"
#include "util.h"
+#include "extract-word.h"
Machine* machine_new(Manager *manager, MachineClass class, const char *name) {
Machine *m;
@@ -309,17 +313,26 @@ int machine_load(Machine *m) {
}
if (netif) {
- size_t l, allocated = 0, nr = 0;
- const char *word, *state;
+ size_t allocated = 0, nr = 0;
+ const char *p;
int *ni = NULL;
- FOREACH_WORD(word, l, netif, state) {
- char buf[l+1];
+ p = netif;
+ for(;;) {
+ _cleanup_free_ char *word = NULL;
int ifi;
- *(char*) (mempcpy(buf, word, l)) = 0;
+ r = extract_first_word(&p, &word, NULL, 0);
+ if (r == 0)
+ break;
+ else if (r == -ENOMEM)
+ return log_oom();
+ else if (r < 0) {
+ log_warning_errno(r, "Failed to parse NETIF: %s", netif);
+ continue;
+ }
- if (safe_atoi(buf, &ifi) < 0)
+ if (safe_atoi(word, &ifi) < 0)
continue;
if (ifi <= 0)
continue;
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 23cc74ab54..7e17c7a41c 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -33,6 +33,7 @@
#include "sd-bus.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "cgroup-show.h"
@@ -48,6 +49,7 @@
#include "macro.h"
#include "mkdir.h"
#include "pager.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "ptyfwd.h"
@@ -58,6 +60,7 @@
#include "unit-name.h"
#include "util.h"
#include "verbs.h"
+#include "web-util.h"
static char **arg_property = NULL;
static bool arg_all = false;
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index 3c91fa8644..7827f063c1 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -25,6 +25,7 @@
#include "sd-id128.h"
+#include "alloc-util.h"
#include "btrfs-util.h"
#include "bus-common-errors.h"
#include "bus-util.h"
@@ -39,6 +40,7 @@
#include "machined.h"
#include "path-util.h"
#include "process-util.h"
+#include "stdio-util.h"
#include "strv.h"
#include "unit-name.h"
#include "user-util.h"
diff --git a/src/machine/machined.c b/src/machine/machined.c
index fe229c88a8..d6e7ce67fc 100644
--- a/src/machine/machined.c
+++ b/src/machine/machined.c
@@ -25,9 +25,11 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "cgroup-util.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "formats-util.h"
#include "hostname-util.h"
diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c
index 34bd65cb11..830ca7b89d 100644
--- a/src/modules-load/modules-load.c
+++ b/src/modules-load/modules-load.c
@@ -28,7 +28,9 @@
#include "conf-files.h"
#include "fd-util.h"
+#include "fileio.h"
#include "log.h"
+#include "proc-cmdline.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index acb6b7ce24..97c1fe6560 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -28,15 +28,20 @@
#include "sd-netlink.h"
#include "sd-network.h"
+#include "alloc-util.h"
#include "arphrd-list.h"
#include "device-util.h"
#include "ether-addr-util.h"
#include "hwdb-util.h"
#include "lldp.h"
#include "local-addresses.h"
+#include "locale-util.h"
+#include "locale-util.h"
#include "netlink-util.h"
#include "pager.h"
+#include "parse-util.h"
#include "socket-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c
index 08e0b9a64b..889fe1e30d 100644
--- a/src/network/networkd-address-pool.c
+++ b/src/network/networkd-address-pool.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "networkd-address-pool.h"
#include "networkd.h"
#include "set.h"
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index dcd7b482d3..e550ee5701 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -21,15 +21,17 @@
#include <net/if.h>
+#include "alloc-util.h"
#include "conf-parser.h"
#include "firewall-util.h"
#include "netlink-util.h"
+#include "networkd-address.h"
#include "networkd.h"
+#include "parse-util.h"
#include "set.h"
#include "string-util.h"
#include "utf8.h"
#include "util.h"
-#include "networkd-address.h"
int address_new(Address **ret) {
_cleanup_address_free_ Address *address = NULL;
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 22594a9415..c412a2cc31 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -22,10 +22,11 @@
#include <netinet/ether.h>
#include <linux/if.h>
+#include "alloc-util.h"
+#include "dhcp-lease-internal.h"
#include "hostname-util.h"
-#include "networkd-link.h"
#include "network-internal.h"
-#include "dhcp-lease-internal.h"
+#include "networkd-link.h"
static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
void *userdata) {
diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c
index 9cb63cb79f..c9222b8cb8 100644
--- a/src/network/networkd-fdb.c
+++ b/src/network/networkd-fdb.c
@@ -22,12 +22,12 @@
#include <net/if.h>
#include <net/ethernet.h>
+#include "alloc-util.h"
#include "conf-parser.h"
-#include "util.h"
#include "netlink-util.h"
-
-#include "networkd.h"
#include "networkd-fdb.h"
+#include "networkd.h"
+#include "util.h"
/* create a new FDB entry or get an existing one. */
int fdb_entry_new_static(Network *const network,
diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c
index 1a1524dfb4..7fc4510ac9 100644
--- a/src/network/networkd-link-bus.c
+++ b/src/network/networkd-link-bus.c
@@ -22,8 +22,10 @@
#include "bus-util.h"
#include "strv.h"
-#include "networkd.h"
+#include "alloc-util.h"
#include "networkd-link.h"
+#include "networkd.h"
+#include "parse-util.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 1144c82c17..12ca02868d 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -23,6 +23,7 @@
#include <linux/if.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "bus-util.h"
#include "dhcp-lease-internal.h"
#include "fd-util.h"
@@ -33,6 +34,8 @@
#include "networkd-netdev.h"
#include "set.h"
#include "socket-util.h"
+#include "stdio-util.h"
+#include "string-table.h"
#include "udev-util.h"
#include "util.h"
#include "virt.h"
@@ -346,12 +349,12 @@ static void link_free(Link *link) {
while (!set_isempty(link->addresses))
address_free(set_first(link->addresses));
- set_free(link->addresses);
-
while (!set_isempty(link->addresses_foreign))
address_free(set_first(link->addresses_foreign));
- set_free(link->addresses_foreign);
+ link->addresses = set_free(link->addresses);
+
+ link->addresses_foreign = set_free(link->addresses_foreign);
while ((address = link->pool_addresses)) {
LIST_REMOVE(addresses, link->pool_addresses, address);
diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c
index b281f4fdb6..dafaf2daea 100644
--- a/src/network/networkd-manager-bus.c
+++ b/src/network/networkd-manager-bus.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "bus-util.h"
-
#include "networkd.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState);
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index febfe2ff81..6b2a661ca7 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -25,10 +25,12 @@
#include "sd-daemon.h"
#include "sd-netlink.h"
+#include "alloc-util.h"
#include "bus-util.h"
#include "conf-parser.h"
#include "def.h"
#include "fd-util.h"
+#include "fileio.h"
#include "libudev-private.h"
#include "local-addresses.h"
#include "netlink-util.h"
diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c
index afc1efdcf7..70105b8aa0 100644
--- a/src/network/networkd-netdev-bond.c
+++ b/src/network/networkd-netdev-bond.c
@@ -25,10 +25,12 @@
#include "sd-netlink.h"
+#include "alloc-util.h"
#include "conf-parser.h"
#include "missing.h"
-#include "string-util.h"
#include "networkd-netdev-bond.h"
+#include "string-util.h"
+#include "string-table.h"
/*
* Number of seconds between instances where the bonding
diff --git a/src/network/networkd-netdev-ipvlan.c b/src/network/networkd-netdev-ipvlan.c
index fb0aed0dcb..27cb7d1bf0 100644
--- a/src/network/networkd-netdev-ipvlan.c
+++ b/src/network/networkd-netdev-ipvlan.c
@@ -21,8 +21,9 @@
#include <net/if.h>
-#include "networkd-netdev-ipvlan.h"
#include "conf-parser.h"
+#include "networkd-netdev-ipvlan.h"
+#include "string-table.h"
static const char* const ipvlan_mode_table[_NETDEV_IPVLAN_MODE_MAX] = {
[NETDEV_IPVLAN_MODE_L2] = "L2",
diff --git a/src/network/networkd-netdev-macvlan.c b/src/network/networkd-netdev-macvlan.c
index e17de793ce..7144823b2d 100644
--- a/src/network/networkd-netdev-macvlan.c
+++ b/src/network/networkd-netdev-macvlan.c
@@ -21,8 +21,9 @@
#include <net/if.h>
-#include "networkd-netdev-macvlan.h"
#include "conf-parser.h"
+#include "networkd-netdev-macvlan.h"
+#include "string-table.h"
static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = {
[NETDEV_MACVLAN_MODE_PRIVATE] = "private",
diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c
index bbc4606258..385338849f 100644
--- a/src/network/networkd-netdev-tunnel.c
+++ b/src/network/networkd-netdev-tunnel.c
@@ -30,9 +30,11 @@
#include "conf-parser.h"
#include "missing.h"
#include "networkd-link.h"
+#include "networkd-netdev-tunnel.h"
+#include "parse-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "util.h"
-#include "networkd-netdev-tunnel.h"
#define DEFAULT_TNL_HOP_LIMIT 64
#define IP6_FLOWINFO_FLOWLABEL htonl(0x000FFFFF)
diff --git a/src/network/networkd-netdev-tuntap.c b/src/network/networkd-netdev-tuntap.c
index d04bb9bd9f..851e83537e 100644
--- a/src/network/networkd-netdev-tuntap.c
+++ b/src/network/networkd-netdev-tuntap.c
@@ -23,6 +23,7 @@
#include <net/if.h>
#include <linux/if_tun.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "networkd-netdev-tuntap.h"
#include "user-util.h"
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index bd1129a09b..dd0b400c6a 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -21,6 +21,7 @@
#include <net/if.h>
+#include "alloc-util.h"
#include "conf-files.h"
#include "conf-parser.h"
#include "fd-util.h"
@@ -30,6 +31,8 @@
#include "networkd-netdev.h"
#include "networkd.h"
#include "siphash24.h"
+#include "stat-util.h"
+#include "string-table.h"
#include "string-util.h"
const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
diff --git a/src/network/networkd-network-bus.c b/src/network/networkd-network-bus.c
index 2199b93baa..120760a986 100644
--- a/src/network/networkd-network-bus.c
+++ b/src/network/networkd-network-bus.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "networkd.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 150fd052c2..cc8d019017 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -22,6 +22,7 @@
#include <ctype.h>
#include <net/if.h>
+#include "alloc-util.h"
#include "conf-files.h"
#include "conf-parser.h"
#include "dns-domain.h"
@@ -30,6 +31,9 @@
#include "network-internal.h"
#include "networkd-network.h"
#include "networkd.h"
+#include "parse-util.h"
+#include "stat-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index fcca679093..4a74bc69f3 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -19,13 +19,15 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "conf-parser.h"
#include "in-addr-util.h"
#include "netlink-util.h"
+#include "networkd-route.h"
#include "networkd.h"
+#include "parse-util.h"
#include "string-util.h"
#include "util.h"
-#include "networkd-route.h"
int route_new(Route **ret) {
_cleanup_route_free_ Route *route = NULL;
diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c
index 4e4a4bbd58..17165266ef 100644
--- a/src/network/networkd-util.c
+++ b/src/network/networkd-util.c
@@ -21,6 +21,8 @@
#include "conf-parser.h"
#include "networkd-util.h"
+#include "parse-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/network/networkd-wait-online-link.c b/src/network/networkd-wait-online-link.c
index cc4b46d5b0..c2779ff773 100644
--- a/src/network/networkd-wait-online-link.c
+++ b/src/network/networkd-wait-online-link.c
@@ -22,6 +22,7 @@
#include "sd-network.h"
+#include "alloc-util.h"
#include "networkd-wait-online-link.h"
#include "string-util.h"
diff --git a/src/network/networkd-wait-online-manager.c b/src/network/networkd-wait-online-manager.c
index 112d92a568..0c40ab2bb8 100644
--- a/src/network/networkd-wait-online-manager.c
+++ b/src/network/networkd-wait-online-manager.c
@@ -23,14 +23,13 @@
#include <linux/if.h>
#include <fnmatch.h>
+#include "alloc-util.h"
#include "netlink-util.h"
-
#include "network-internal.h"
#include "networkd-wait-online-link.h"
#include "networkd-wait-online.h"
-
-#include "util.h"
#include "time-util.h"
+#include "util.h"
bool manager_ignore_link(Manager *m, Link *link) {
char **ignore;
diff --git a/src/network/networkd.c b/src/network/networkd.c
index 1a17847715..c03ac69e27 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -21,7 +21,7 @@
#include "sd-daemon.h"
-#include "capability.h"
+#include "capability-util.h"
#include "networkd.h"
#include "signal-util.h"
#include "user-util.h"
diff --git a/src/network/test-network.c b/src/network/test-network.c
index bac1d6781d..dbed3795e3 100644
--- a/src/network/test-network.c
+++ b/src/network/test-network.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "networkd.h"
#include "network-internal.h"
#include "dhcp-lease-internal.h"
diff --git a/src/notify/notify.c b/src/notify/notify.c
index 288e0a4316..b144554702 100644
--- a/src/notify/notify.c
+++ b/src/notify/notify.c
@@ -27,9 +27,11 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "env-util.h"
#include "formats-util.h"
#include "log.h"
+#include "parse-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c
index 4e86ed13cb..270bcf010f 100644
--- a/src/nspawn/nspawn-cgroup.c
+++ b/src/nspawn/nspawn-cgroup.c
@@ -21,6 +21,7 @@
#include <sys/mount.h>
+#include "alloc-util.h"
#include "cgroup-util.h"
#include "fd-util.h"
#include "fileio.h"
diff --git a/src/nspawn/nspawn-expose-ports.c b/src/nspawn/nspawn-expose-ports.c
index 98e4a7682f..38245434da 100644
--- a/src/nspawn/nspawn-expose-ports.c
+++ b/src/nspawn/nspawn-expose-ports.c
@@ -21,12 +21,14 @@
#include "sd-netlink.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "firewall-util.h"
#include "in-addr-util.h"
#include "local-addresses.h"
#include "netlink-util.h"
#include "nspawn-expose-ports.h"
+#include "parse-util.h"
#include "socket-util.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c
index 25457fd62d..ee61306aa5 100644
--- a/src/nspawn/nspawn-mount.c
+++ b/src/nspawn/nspawn-mount.c
@@ -22,17 +22,23 @@
#include <sys/mount.h>
#include <linux/magic.h>
+#include "alloc-util.h"
#include "cgroup-util.h"
#include "escape.h"
+#include "fs-util.h"
#include "label.h"
#include "mkdir.h"
+#include "mount-util.h"
+#include "nspawn-mount.h"
+#include "parse-util.h"
#include "path-util.h"
#include "rm-rf.h"
#include "set.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
+#include "user-util.h"
#include "util.h"
-#include "nspawn-mount.h"
CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t) {
CustomMount *c, *ret;
diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c
index 4af18a4e94..29384b60b2 100644
--- a/src/nspawn/nspawn-network.c
+++ b/src/nspawn/nspawn-network.c
@@ -26,6 +26,7 @@
#include "sd-id128.h"
#include "sd-netlink.h"
+#include "alloc-util.h"
#include "ether-addr-util.h"
#include "netlink-util.h"
#include "siphash24.h"
diff --git a/src/nspawn/nspawn-register.c b/src/nspawn/nspawn-register.c
index b2776a61c2..7139ad9958 100644
--- a/src/nspawn/nspawn-register.c
+++ b/src/nspawn/nspawn-register.c
@@ -21,12 +21,12 @@
#include "sd-bus.h"
-#include "util.h"
-#include "strv.h"
-#include "bus-util.h"
#include "bus-error.h"
-
+#include "bus-util.h"
#include "nspawn-register.h"
+#include "stat-util.h"
+#include "strv.h"
+#include "util.h"
int register_machine(
const char *machine_name,
diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c
index f088884776..6885d0641e 100644
--- a/src/nspawn/nspawn-settings.c
+++ b/src/nspawn/nspawn-settings.c
@@ -19,12 +19,13 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "conf-parser.h"
-#include "strv.h"
+#include "alloc-util.h"
#include "cap-list.h"
-
+#include "conf-parser.h"
#include "nspawn-settings.h"
+#include "process-util.h"
+#include "strv.h"
+#include "util.h"
int settings_load(FILE *f, const char *path, Settings **ret) {
_cleanup_(settings_freep) Settings *s = NULL;
diff --git a/src/nspawn/nspawn-setuid.c b/src/nspawn/nspawn-setuid.c
index 6b4ca5a3f3..aa6a16309c 100644
--- a/src/nspawn/nspawn-setuid.c
+++ b/src/nspawn/nspawn-setuid.c
@@ -23,6 +23,7 @@
#include <sys/types.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "mkdir.h"
#include "nspawn-setuid.h"
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 6502fe1943..ff12ca6498 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -46,12 +46,13 @@
#include "sd-daemon.h"
#include "sd-id128.h"
+#include "alloc-util.h"
#include "barrier.h"
#include "base-filesystem.h"
#include "blkid-util.h"
#include "btrfs-util.h"
#include "cap-list.h"
-#include "capability.h"
+#include "capability-util.h"
#include "cgroup-util.h"
#include "copy.h"
#include "dev-setup.h"
@@ -61,6 +62,7 @@
#include "fdset.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "gpt.h"
#include "hostname-util.h"
#include "log.h"
@@ -69,6 +71,7 @@
#include "macro.h"
#include "missing.h"
#include "mkdir.h"
+#include "mount-util.h"
#include "netlink-util.h"
#include "nspawn-cgroup.h"
#include "nspawn-expose-ports.h"
@@ -77,6 +80,7 @@
#include "nspawn-register.h"
#include "nspawn-settings.h"
#include "nspawn-setuid.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "ptyfwd.h"
@@ -87,10 +91,13 @@
#endif
#include "signal-util.h"
#include "socket-util.h"
+#include "stat-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "udev-util.h"
+#include "umask-util.h"
#include "user-util.h"
#include "util.h"
@@ -380,6 +387,7 @@ static int parse_argv(int argc, char *argv[]) {
};
int c, r;
+ const char *p;
uint64_t plus = 0, minus = 0;
bool mask_all_settings = false, mask_no_settings = false;
@@ -517,15 +525,16 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_CAPABILITY:
case ARG_DROP_CAPABILITY: {
- const char *state, *word;
- size_t length;
+ p = optarg;
+ for(;;) {
+ _cleanup_free_ char *t = NULL;
- FOREACH_WORD_SEPARATOR(word, length, optarg, ",", state) {
- _cleanup_free_ char *t;
+ r = extract_first_word(&p, &t, ",", 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse capability %s.", t);
- t = strndup(word, length);
- if (!t)
- return log_oom();
+ if (r == 0)
+ break;
if (streq(t, "all")) {
if (c == ARG_CAPABILITY)
@@ -3218,8 +3227,7 @@ int main(int argc, char *argv[]) {
}
for (;;) {
- _cleanup_close_pair_ int kmsg_socket_pair[2] = { -1, -1 }, rtnl_socket_pair[2] = { -1, -1 }, pid_socket_pair[2] = { -1, -1 },
- uid_shift_socket_pair[2] = { -1, -1 };
+ _cleanup_close_pair_ int kmsg_socket_pair[2] = { -1, -1 }, rtnl_socket_pair[2] = { -1, -1 }, pid_socket_pair[2] = { -1, -1 }, uid_shift_socket_pair[2] = { -1, -1 };
ContainerStatus container_status;
_cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
static const struct sigaction sa = {
diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c
index 009a9ad886..ee10b105ea 100644
--- a/src/nss-myhostname/nss-myhostname.c
+++ b/src/nss-myhostname/nss-myhostname.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <string.h>
+#include "alloc-util.h"
#include "hostname-util.h"
#include "local-addresses.h"
#include "macro.h"
diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c
index b98bde676b..969fa9619e 100644
--- a/src/nss-mymachines/nss-mymachines.c
+++ b/src/nss-mymachines/nss-mymachines.c
@@ -25,6 +25,7 @@
#include "sd-bus.h"
#include "sd-login.h"
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-util.h"
#include "hostname-util.h"
diff --git a/src/path/path.c b/src/path/path.c
index 97e8323de1..0ece72f6fe 100644
--- a/src/path/path.c
+++ b/src/path/path.c
@@ -26,6 +26,7 @@
#include "sd-path.h"
+#include "alloc-util.h"
#include "log.h"
#include "macro.h"
#include "string-util.h"
diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c
index a2a035f4f1..dc2911e4e8 100644
--- a/src/quotacheck/quotacheck.c
+++ b/src/quotacheck/quotacheck.c
@@ -29,6 +29,7 @@
#include "signal-util.h"
#include "string-util.h"
#include "util.h"
+#include "proc-cmdline.h"
static bool arg_skip = false;
static bool arg_force = false;
diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c
index fbfd3a3eba..d857ade36a 100644
--- a/src/random-seed/random-seed.c
+++ b/src/random-seed/random-seed.c
@@ -25,6 +25,7 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "io-util.h"
#include "log.h"
diff --git a/src/rc-local-generator/rc-local-generator.c b/src/rc-local-generator/rc-local-generator.c
index 1007de3959..8e5cf0908c 100644
--- a/src/rc-local-generator/rc-local-generator.c
+++ b/src/rc-local-generator/rc-local-generator.c
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "log.h"
#include "mkdir.h"
#include "string-util.h"
diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c
index f904e48e75..57f99c9ef0 100644
--- a/src/remount-fs/remount-fs.c
+++ b/src/remount-fs/remount-fs.c
@@ -26,12 +26,13 @@
#include <sys/wait.h>
#include <mntent.h>
+#include "exit-status.h"
#include "log.h"
-#include "util.h"
+#include "mount-setup.h"
+#include "mount-util.h"
#include "path-util.h"
#include "signal-util.h"
-#include "mount-setup.h"
-#include "exit-status.h"
+#include "util.h"
/* Goes through /etc/fstab and remounts all API file systems, applying
* options that are in /etc/fstab that systemd might not have
diff --git a/src/resolve-host/resolve-host.c b/src/resolve-host/resolve-host.c
index 97516a87a8..57739d1f3e 100644
--- a/src/resolve-host/resolve-host.c
+++ b/src/resolve-host/resolve-host.c
@@ -25,9 +25,11 @@
#include "sd-bus.h"
#include "af-list.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "in-addr-util.h"
+#include "parse-util.h"
#include "resolved-def.h"
#include "resolved-dns-packet.h"
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
index bf1b7c8ab4..f0a3b607d4 100644
--- a/src/resolve/resolved-bus.c
+++ b/src/resolve/resolved-bus.c
@@ -19,9 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-util.h"
-
#include "dns-domain.h"
#include "resolved-bus.h"
#include "resolved-def.h"
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c
index aca0d891c6..c9919ced67 100644
--- a/src/resolve/resolved-conf.c
+++ b/src/resolve/resolved-conf.c
@@ -19,13 +19,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "conf-parser.h"
-#include "string-util.h"
+#include "extract-word.h"
+#include "parse-util.h"
#include "resolved-conf.h"
+#include "string-util.h"
int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string) {
- const char *word, *state;
- size_t length;
DnsServer *first;
int r;
@@ -34,19 +35,22 @@ int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string)
first = type == DNS_SERVER_FALLBACK ? m->fallback_dns_servers : m->dns_servers;
- FOREACH_WORD_QUOTED(word, length, string, state) {
- char buffer[length+1];
- int family;
+ for(;;) {
+ _cleanup_free_ char *word = NULL;
union in_addr_union addr;
bool found = false;
DnsServer *s;
+ int family;
- memcpy(buffer, word, length);
- buffer[length] = 0;
+ r = extract_first_word(&string, &word, NULL, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse resolved dns server syntax \"%s\": %m", string);
+ if (r == 0)
+ break;
- r = in_addr_from_string_auto(buffer, &family, &addr);
+ r = in_addr_from_string_auto(word, &family, &addr);
if (r < 0) {
- log_warning("Ignoring invalid DNS address '%s'", buffer);
+ log_warning("Ignoring invalid DNS address '%s'", word);
continue;
}
diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c
index e1a2865007..3cf9c68074 100644
--- a/src/resolve/resolved-dns-answer.c
+++ b/src/resolve/resolved-dns-answer.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "dns-domain.h"
#include "resolved-dns-answer.h"
#include "string-util.h"
diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c
index ab13636bc1..04f64022e0 100644
--- a/src/resolve/resolved-dns-cache.c
+++ b/src/resolve/resolved-dns-cache.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "resolved-dns-cache.h"
#include "resolved-dns-packet.h"
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index bebd1ee4a6..f23b3cf893 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -19,12 +19,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "utf8.h"
-#include "util.h"
-#include "strv.h"
-#include "unaligned.h"
+#include "alloc-util.h"
#include "dns-domain.h"
#include "resolved-dns-packet.h"
+#include "string-table.h"
+#include "strv.h"
+#include "unaligned.h"
+#include "utf8.h"
+#include "util.h"
int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
DnsPacket *p;
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
index 4b1d18b2ef..f7cb84e2a6 100644
--- a/src/resolve/resolved-dns-query.c
+++ b/src/resolve/resolved-dns-query.c
@@ -19,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "hostname-util.h"
+#include "alloc-util.h"
#include "dns-domain.h"
+#include "hostname-util.h"
#include "local-addresses.h"
-
#include "resolved-dns-query.h"
/* How long to wait for the query in total */
diff --git a/src/resolve/resolved-dns-question.c b/src/resolve/resolved-dns-question.c
index 1507f22da0..48951221dc 100644
--- a/src/resolve/resolved-dns-question.c
+++ b/src/resolve/resolved-dns-question.c
@@ -19,8 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "resolved-dns-question.h"
+#include "alloc-util.h"
#include "dns-domain.h"
+#include "resolved-dns-question.h"
DnsQuestion *dns_question_new(unsigned n) {
DnsQuestion *q;
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c
index c8f591d005..ba2ea686f3 100644
--- a/src/resolve/resolved-dns-rr.c
+++ b/src/resolve/resolved-dns-rr.c
@@ -21,12 +21,14 @@
#include <math.h>
+#include "alloc-util.h"
#include "dns-domain.h"
#include "dns-type.h"
+#include "hexdecoct.h"
#include "resolved-dns-packet.h"
+#include "resolved-dns-rr.h"
#include "string-util.h"
#include "strv.h"
-#include "resolved-dns-rr.h"
DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
DnsResourceKey *k;
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 7c63c63b63..b15370b017 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -22,6 +22,7 @@
#include <netinet/tcp.h>
#include "af-list.h"
+#include "alloc-util.h"
#include "dns-domain.h"
#include "fd-util.h"
#include "hostname-util.h"
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index 8693911e65..e803f635ab 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -19,9 +19,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "siphash24.h"
-
+#include "alloc-util.h"
#include "resolved-dns-server.h"
+#include "siphash24.h"
/* After how much time to repeat classic DNS requests */
#define DNS_TIMEOUT_MIN_USEC (500 * USEC_PER_MSEC)
diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c
index b2eebe09a2..1c501182fb 100644
--- a/src/resolve/resolved-dns-stream.c
+++ b/src/resolve/resolved-dns-stream.c
@@ -21,7 +21,9 @@
#include <netinet/tcp.h>
+#include "alloc-util.h"
#include "fd-util.h"
+#include "io-util.h"
#include "missing.h"
#include "resolved-dns-stream.h"
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 84472ca1bc..6545f6cd8a 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -20,12 +20,13 @@
***/
#include "af-list.h"
-
+#include "alloc-util.h"
#include "dns-domain.h"
#include "fd-util.h"
#include "random-util.h"
#include "resolved-dns-transaction.h"
#include "resolved-llmnr.h"
+#include "string-table.h"
DnsTransaction* dns_transaction_free(DnsTransaction *t) {
DnsQuery *q;
diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c
index 8a6086a4de..48dcf76daa 100644
--- a/src/resolve/resolved-dns-zone.c
+++ b/src/resolve/resolved-dns-zone.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "dns-domain.h"
#include "list.h"
#include "resolved-dns-packet.h"
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index 43a3b61b08..2892641075 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -23,7 +23,9 @@
#include "sd-network.h"
+#include "alloc-util.h"
#include "missing.h"
+#include "parse-util.h"
#include "resolved-link.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 6144eedfeb..a588538b52 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -25,6 +25,7 @@
#include <sys/ioctl.h>
#include "af-list.h"
+#include "alloc-util.h"
#include "dns-domain.h"
#include "fd-util.h"
#include "fileio-label.h"
@@ -33,12 +34,14 @@
#include "netlink-util.h"
#include "network-internal.h"
#include "ordered-set.h"
+#include "parse-util.h"
#include "random-util.h"
#include "resolved-bus.h"
#include "resolved-conf.h"
#include "resolved-llmnr.h"
#include "resolved-manager.h"
#include "socket-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "utf8.h"
diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c
index df4eb6f63e..7ba0546f4a 100644
--- a/src/resolve/resolved.c
+++ b/src/resolve/resolved.c
@@ -22,7 +22,7 @@
#include "sd-daemon.h"
#include "sd-event.h"
-#include "capability.h"
+#include "capability-util.h"
#include "mkdir.h"
#include "resolved-conf.h"
#include "resolved-manager.h"
diff --git a/src/rfkill/rfkill.c b/src/rfkill/rfkill.c
index 311343e454..bb00f99ecf 100644
--- a/src/rfkill/rfkill.c
+++ b/src/rfkill/rfkill.c
@@ -25,11 +25,15 @@
#include "libudev.h"
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
#include "io-util.h"
#include "mkdir.h"
+#include "parse-util.h"
+#include "proc-cmdline.h"
+#include "string-table.h"
#include "string-util.h"
#include "udev-util.h"
#include "util.h"
diff --git a/src/run/run.c b/src/run/run.c
index 3646305961..38a482bb11 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -25,6 +25,7 @@
#include "sd-bus.h"
#include "sd-event.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
#include "calendarspec.h"
@@ -40,6 +41,7 @@
#include "terminal-util.h"
#include "unit-name.h"
#include "user-util.h"
+#include "parse-util.h"
static bool arg_ask_password = true;
static bool arg_scope = false;
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
index e8931daee2..79f5a60579 100644
--- a/src/shared/acl-util.c
+++ b/src/shared/acl-util.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include <stdbool.h>
+#include "alloc-util.h"
#include "acl-util.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c
index b3d2f96885..8e36067f74 100644
--- a/src/shared/acpi-fpdt.c
+++ b/src/shared/acpi-fpdt.c
@@ -25,6 +25,7 @@
#include <string.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "acpi-fpdt.h"
#include "fd-util.h"
#include "fileio.h"
diff --git a/src/shared/apparmor-util.c b/src/shared/apparmor-util.c
index c2bbd330bd..f6ac43adfe 100644
--- a/src/shared/apparmor-util.c
+++ b/src/shared/apparmor-util.c
@@ -19,10 +19,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-
-#include "util.h"
-#include "fileio.h"
+#include "alloc-util.h"
#include "apparmor-util.h"
+#include "fileio.h"
+#include "parse-util.h"
+#include "util.h"
bool mac_apparmor_use(void) {
static int cached_use = -1;
diff --git a/src/shared/architecture.c b/src/shared/architecture.c
index e5efcd77b6..e2efa4272b 100644
--- a/src/shared/architecture.c
+++ b/src/shared/architecture.c
@@ -21,6 +21,7 @@
#include <sys/utsname.h>
+#include "string-table.h"
#include "string-util.h"
#include "architecture.h"
diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c
index 15203d21ea..c96dbf877a 100644
--- a/src/shared/ask-password-api.c
+++ b/src/shared/ask-password-api.c
@@ -32,8 +32,10 @@
#include <termios.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "ask-password-api.h"
#include "fd-util.h"
+#include "fileio.h"
#include "formats-util.h"
#include "io-util.h"
#include "missing.h"
@@ -44,6 +46,7 @@
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
+#include "umask-util.h"
#include "util.h"
#define KEYRING_TIMEOUT_USEC ((5 * USEC_PER_MINUTE) / 2)
diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c
index 751dfdec45..e605490c32 100644
--- a/src/shared/base-filesystem.c
+++ b/src/shared/base-filesystem.c
@@ -24,12 +24,15 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "alloc-util.h"
+#include "base-filesystem.h"
+#include "fd-util.h"
#include "log.h"
#include "macro.h"
#include "string-util.h"
+#include "umask-util.h"
+#include "user-util.h"
#include "util.h"
-#include "base-filesystem.h"
-#include "fd-util.h"
typedef struct BaseFilesystem {
const char *dir;
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index e6c5875766..a13991a960 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -25,6 +25,7 @@
#include "sd-daemon.h"
#include "sd-event.h"
+#include "alloc-util.h"
#include "bus-error.h"
#include "bus-internal.h"
#include "bus-label.h"
@@ -37,12 +38,19 @@
#include "fd-util.h"
#include "macro.h"
#include "missing.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "proc-cmdline.h"
+#include "process-util.h"
+#include "rlimit-util.h"
#include "set.h"
#include "signal-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
+#include "syslog-util.h"
#include "unit-name.h"
+#include "user-util.h"
#include "utf8.h"
#include "util.h"
@@ -1442,7 +1450,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
"SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
"PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
- "SyslogLevelPrefix")) {
+ "SyslogLevelPrefix", "Delegate")) {
r = parse_boolean(eq);
if (r < 0) {
diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c
index 395e41930c..129ffc7056 100644
--- a/src/shared/cgroup-show.c
+++ b/src/shared/cgroup-show.c
@@ -24,10 +24,12 @@
#include <stdio.h>
#include <string.h>
+#include "alloc-util.h"
#include "cgroup-show.h"
#include "cgroup-util.h"
#include "fd-util.h"
#include "formats-util.h"
+#include "locale-util.h"
#include "macro.h"
#include "path-util.h"
#include "process-util.h"
diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c
index fe3187384f..c60f605997 100644
--- a/src/shared/clean-ipc.c
+++ b/src/shared/clean-ipc.c
@@ -30,10 +30,12 @@
#include "clean-ipc.h"
#include "fd-util.h"
+#include "fileio.h"
#include "formats-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
+#include "dirent-util.h"
static int clean_sysvipc_shm(uid_t delete_uid) {
_cleanup_fclose_ FILE *f = NULL;
diff --git a/src/shared/condition.c b/src/shared/condition.c
index b8915dab8a..a69719116c 100644
--- a/src/shared/condition.c
+++ b/src/shared/condition.c
@@ -27,18 +27,25 @@
#include "sd-id128.h"
+#include "alloc-util.h"
#include "apparmor-util.h"
#include "architecture.h"
-#include "audit.h"
+#include "audit-util.h"
#include "cap-list.h"
#include "condition.h"
#include "extract-word.h"
#include "fd-util.h"
+#include "glob-util.h"
#include "hostname-util.h"
#include "ima-util.h"
+#include "mount-util.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "proc-cmdline.h"
#include "selinux-util.h"
#include "smack-util.h"
+#include "stat-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "util.h"
#include "virt.h"
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index 1b47c0ab52..3f8eaf7d9a 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -26,17 +26,22 @@
#include "sd-messages.h"
+#include "alloc-util.h"
#include "conf-files.h"
+#include "conf-parser.h"
+#include "fd-util.h"
+#include "fs-util.h"
#include "log.h"
#include "macro.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "process-util.h"
#include "signal-util.h"
#include "string-util.h"
#include "strv.h"
+#include "syslog-util.h"
#include "utf8.h"
#include "util.h"
-#include "conf-parser.h"
-#include "fd-util.h"
int config_item_table_lookup(
const void *table,
diff --git a/src/shared/dev-setup.c b/src/shared/dev-setup.c
index 25ad918b85..ad3c17d5bd 100644
--- a/src/shared/dev-setup.c
+++ b/src/shared/dev-setup.c
@@ -23,10 +23,12 @@
#include <stdlib.h>
#include <unistd.h>
-#include "util.h"
+#include "alloc-util.h"
+#include "dev-setup.h"
#include "label.h"
#include "path-util.h"
-#include "dev-setup.h"
+#include "user-util.h"
+#include "util.h"
int dev_setup(const char *prefix, uid_t uid, gid_t gid) {
static const char symlinks[] =
diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c
index d4df9d2acb..7af15e0098 100644
--- a/src/shared/dns-domain.c
+++ b/src/shared/dns-domain.c
@@ -24,8 +24,11 @@
#include <stringprep.h>
#endif
-#include "string-util.h"
+#include "alloc-util.h"
#include "dns-domain.h"
+#include "hexdecoct.h"
+#include "parse-util.h"
+#include "string-util.h"
int dns_label_unescape(const char **name, char *dest, size_t sz) {
const char *n;
diff --git a/src/shared/dropin.c b/src/shared/dropin.c
index 1836e91acd..0d44401cc2 100644
--- a/src/shared/dropin.c
+++ b/src/shared/dropin.c
@@ -19,12 +19,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "conf-files.h"
#include "dropin.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio-label.h"
#include "mkdir.h"
+#include "path-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
diff --git a/src/shared/efivars.c b/src/shared/efivars.c
index 4808ede60c..86bb0b57c3 100644
--- a/src/shared/efivars.c
+++ b/src/shared/efivars.c
@@ -23,9 +23,13 @@
#include <string.h>
#include <fcntl.h>
+#include "alloc-util.h"
+#include "dirent-util.h"
#include "efivars.h"
#include "fd-util.h"
#include "io-util.h"
+#include "parse-util.h"
+#include "stdio-util.h"
#include "utf8.h"
#include "util.h"
#include "virt.h"
diff --git a/src/shared/firewall-util.c b/src/shared/firewall-util.c
index effc6e8e70..e178287872 100644
--- a/src/shared/firewall-util.c
+++ b/src/shared/firewall-util.c
@@ -27,8 +27,9 @@
#include <linux/netfilter/xt_addrtype.h>
#include <libiptc/libiptc.h>
-#include "util.h"
+#include "alloc-util.h"
#include "firewall-util.h"
+#include "util.h"
DEFINE_TRIVIAL_CLEANUP_FUNC(struct xtc_handle*, iptc_free);
diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c
index bdfc13e3cd..eb2845cddf 100644
--- a/src/shared/fstab-util.c
+++ b/src/shared/fstab-util.c
@@ -19,11 +19,15 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
+#include "device-nodes.h"
+#include "fstab-util.h"
+#include "mount-util.h"
+#include "parse-util.h"
#include "path-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
-#include "fstab-util.h"
bool fstab_is_mount_point(const char *mount) {
_cleanup_endmntent_ FILE *f = NULL;
@@ -195,3 +199,60 @@ int fstab_find_pri(const char *options, int *ret) {
*ret = (int) pri;
return 1;
}
+
+static char *unquote(const char *s, const char* quotes) {
+ size_t l;
+ assert(s);
+
+ /* This is rather stupid, simply removes the heading and
+ * trailing quotes if there is one. Doesn't care about
+ * escaping or anything.
+ *
+ * DON'T USE THIS FOR NEW CODE ANYMORE!*/
+
+ l = strlen(s);
+ if (l < 2)
+ return strdup(s);
+
+ if (strchr(quotes, s[0]) && s[l-1] == s[0])
+ return strndup(s+1, l-2);
+
+ return strdup(s);
+}
+
+static char *tag_to_udev_node(const char *tagvalue, const char *by) {
+ _cleanup_free_ char *t = NULL, *u = NULL;
+ size_t enc_len;
+
+ u = unquote(tagvalue, QUOTES);
+ if (!u)
+ return NULL;
+
+ enc_len = strlen(u) * 4 + 1;
+ t = new(char, enc_len);
+ if (!t)
+ return NULL;
+
+ if (encode_devnode_name(u, t, enc_len) < 0)
+ return NULL;
+
+ return strjoin("/dev/disk/by-", by, "/", t, NULL);
+}
+
+char *fstab_node_to_udev_node(const char *p) {
+ assert(p);
+
+ if (startswith(p, "LABEL="))
+ return tag_to_udev_node(p+6, "label");
+
+ if (startswith(p, "UUID="))
+ return tag_to_udev_node(p+5, "uuid");
+
+ if (startswith(p, "PARTUUID="))
+ return tag_to_udev_node(p+9, "partuuid");
+
+ if (startswith(p, "PARTLABEL="))
+ return tag_to_udev_node(p+10, "partlabel");
+
+ return strdup(p);
+}
diff --git a/src/shared/fstab-util.h b/src/shared/fstab-util.h
index 872b2363cd..5ebea44019 100644
--- a/src/shared/fstab-util.h
+++ b/src/shared/fstab-util.h
@@ -23,11 +23,12 @@
#include <stdbool.h>
#include <stddef.h>
+
#include "macro.h"
bool fstab_is_mount_point(const char *mount);
-int fstab_filter_options(const char *opts, const char *names,
- const char **namefound, char **value, char **filtered);
+
+int fstab_filter_options(const char *opts, const char *names, const char **namefound, char **value, char **filtered);
int fstab_extract_values(const char *opts, const char *name, char ***values);
@@ -49,3 +50,5 @@ static inline bool fstab_test_yes_no_option(const char *opts, const char *yes_no
return opt == yes_no;
}
+
+char *fstab_node_to_udev_node(const char *p);
diff --git a/src/shared/generator.c b/src/shared/generator.c
index 0a8e282949..cb4ebc606e 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -21,6 +21,7 @@
#include <unistd.h>
+#include "alloc-util.h"
#include "dropin.h"
#include "escape.h"
#include "fd-util.h"
@@ -28,6 +29,7 @@
#include "fstab-util.h"
#include "generator.h"
#include "mkdir.h"
+#include "mount-util.h"
#include "path-util.h"
#include "special.h"
#include "string-util.h"
diff --git a/src/shared/import-util.c b/src/shared/import-util.c
index c4c66c847d..ddc8c00a2d 100644
--- a/src/shared/import-util.c
+++ b/src/shared/import-util.c
@@ -19,10 +19,13 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "btrfs-util.h"
+#include "import-util.h"
+#include "path-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "util.h"
-#include "import-util.h"
int import_url_last_component(const char *url, char **ret) {
const char *e, *p;
diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c
index 224874f65c..e1cb5d27ff 100644
--- a/src/shared/install-printf.c
+++ b/src/shared/install-printf.c
@@ -21,6 +21,7 @@
#include <stdlib.h>
+#include "alloc-util.h"
#include "formats-util.h"
#include "install-printf.h"
#include "specifier.h"
diff --git a/src/shared/install.c b/src/shared/install.c
index 9b72f76662..b7d1d22505 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -25,21 +25,26 @@
#include <string.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "conf-files.h"
#include "conf-parser.h"
+#include "dirent-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "install-printf.h"
+#include "install.h"
#include "mkdir.h"
#include "path-lookup.h"
#include "path-util.h"
#include "set.h"
#include "special.h"
+#include "stat-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
#include "util.h"
-#include "install.h"
-#include "fd-util.h"
typedef struct {
OrderedHashmap *will_install;
@@ -48,13 +53,12 @@ typedef struct {
static int in_search_path(const char *path, char **search) {
_cleanup_free_ char *parent = NULL;
- int r;
assert(path);
- r = path_get_parent(path, &parent);
- if (r < 0)
- return r;
+ parent = dirname_malloc(path);
+ if (!parent)
+ return -ENOMEM;
return strv_contains(search, parent);
}
@@ -925,8 +929,6 @@ static int config_parse_also(
void *data,
void *userdata) {
- size_t l;
- const char *word, *state;
InstallContext *c = data;
UnitFileInstallInfo *i = userdata;
@@ -934,13 +936,18 @@ static int config_parse_also(
assert(lvalue);
assert(rvalue);
- FOREACH_WORD_QUOTED(word, l, rvalue, state) {
- _cleanup_free_ char *n;
+ for(;;) {
+ _cleanup_free_ char *n = NULL;
int r;
- n = strndup(word, l);
- if (!n)
- return -ENOMEM;
+ r = extract_first_word(&rvalue, &n, NULL, 0);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse config %s, ignoring.", rvalue);
+ return 0;
+ }
+
+ if (r == 0)
+ break;
r = install_info_add(c, n, NULL);
if (r < 0)
@@ -950,8 +957,6 @@ static int config_parse_also(
if (r < 0)
return r;
}
- if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
return 0;
}
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index d8ea4c9f92..0313b0946f 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -25,6 +25,7 @@
#include <sys/socket.h>
#include <time.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "formats-util.h"
#include "hashmap.h"
@@ -33,7 +34,9 @@
#include "journal-internal.h"
#include "log.h"
#include "logs-show.h"
+#include "parse-util.h"
#include "process-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "terminal-util.h"
#include "utf8.h"
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index 415d939fc6..2c1da0a40d 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -23,16 +23,22 @@
#include <linux/fs.h>
#include <sys/statfs.h>
+#include "alloc-util.h"
#include "btrfs-util.h"
+#include "chattr-util.h"
#include "copy.h"
+#include "dirent-util.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "machine-image.h"
#include "mkdir.h"
#include "path-util.h"
#include "rm-rf.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
+#include "xattr-util.h"
static const char image_search_path[] =
"/var/lib/machines\0"
diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c
index a2cb5fc5a0..60b1b3092d 100644
--- a/src/shared/machine-pool.c
+++ b/src/shared/machine-pool.c
@@ -24,14 +24,20 @@
#include <sys/statvfs.h>
#include <sys/vfs.h>
+#include "alloc-util.h"
#include "btrfs-util.h"
#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "lockfile-util.h"
#include "machine-pool.h"
#include "mkdir.h"
+#include "mount-util.h"
+#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "signal-util.h"
+#include "stat-util.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/shared/pager.c b/src/shared/pager.c
index 7029d6b2e2..d149bc1722 100644
--- a/src/shared/pager.c
+++ b/src/shared/pager.c
@@ -27,6 +27,7 @@
#include "copy.h"
#include "fd-util.h"
+#include "locale-util.h"
#include "macro.h"
#include "pager.h"
#include "process-util.h"
diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c
index 1e63c72047..d71f379e76 100644
--- a/src/shared/path-lookup.c
+++ b/src/shared/path-lookup.c
@@ -24,6 +24,7 @@
#include <string.h>
#include <errno.h>
+#include "alloc-util.h"
#include "util.h"
#include "strv.h"
#include "path-util.h"
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
index e5e0f37adf..63e81f4894 100644
--- a/src/shared/ptyfwd.c
+++ b/src/shared/ptyfwd.c
@@ -24,6 +24,7 @@
#include <limits.h>
#include <termios.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "ptyfwd.h"
#include "util.h"
@@ -412,6 +413,7 @@ PTYForward *pty_forward_free(PTYForward *f) {
sd_event_source_unref(f->stdin_event_source);
sd_event_source_unref(f->stdout_event_source);
sd_event_source_unref(f->master_event_source);
+ sd_event_source_unref(f->sigwinch_event_source);
sd_event_unref(f->event);
if (f->saved_stdout)
diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c
index b5cb9508bf..bbbb3460d4 100644
--- a/src/shared/sleep-config.c
+++ b/src/shared/sleep-config.c
@@ -21,6 +21,7 @@
#include <stdio.h>
+#include "alloc-util.h"
#include "conf-parser.h"
#include "fd-util.h"
#include "fileio.h"
@@ -29,6 +30,7 @@
#include "string-util.h"
#include "strv.h"
#include "util.h"
+#include "parse-util.h"
#define USE(x, y) do{ (x) = (y); (y) = NULL; } while(0)
diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c
index 7cc9e7ccc1..ec6e5a8312 100644
--- a/src/shared/spawn-polkit-agent.c
+++ b/src/shared/spawn-polkit-agent.c
@@ -30,6 +30,7 @@
#include "log.h"
#include "process-util.h"
#include "spawn-polkit-agent.h"
+#include "stdio-util.h"
#include "util.h"
#ifdef ENABLE_POLKIT
@@ -78,8 +79,9 @@ void polkit_agent_close(void) {
return;
/* Inform agent that we are done */
- kill(agent_pid, SIGTERM);
- kill(agent_pid, SIGCONT);
+ (void) kill(agent_pid, SIGTERM);
+ (void) kill(agent_pid, SIGCONT);
+
(void) wait_for_terminate(agent_pid, NULL);
agent_pid = 0;
}
diff --git a/src/shared/specifier.c b/src/shared/specifier.c
index 610aec0df5..c5c4a4d7d7 100644
--- a/src/shared/specifier.c
+++ b/src/shared/specifier.c
@@ -22,11 +22,12 @@
#include <string.h>
#include <sys/utsname.h>
+#include "alloc-util.h"
#include "hostname-util.h"
#include "macro.h"
+#include "specifier.h"
#include "string-util.h"
#include "util.h"
-#include "specifier.h"
/*
* Generic infrastructure for replacing %x style specifiers in
diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c
index 60d7043fda..fc885f6cb8 100644
--- a/src/shared/switch-root.c
+++ b/src/shared/switch-root.c
@@ -35,6 +35,7 @@
#include "rm-rf.h"
#include "string-util.h"
#include "switch-root.h"
+#include "user-util.h"
#include "util.h"
int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot, unsigned long mountflags) {
diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c
index 1e6ac2f27d..13b32a0509 100644
--- a/src/shared/utmp-wtmp.c
+++ b/src/shared/utmp-wtmp.c
@@ -27,6 +27,7 @@
#include <unistd.h>
#include <utmpx.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "hostname-util.h"
#include "macro.h"
diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c
index e82fb06417..ba82adadb4 100644
--- a/src/socket-proxy/socket-proxyd.c
+++ b/src/socket-proxy/socket-proxyd.c
@@ -34,6 +34,7 @@
#include "sd-event.h"
#include "sd-resolve.h"
+#include "alloc-util.h"
#include "fd-util.h"
#include "log.h"
#include "path-util.h"
diff --git a/src/system-update-generator/system-update-generator.c b/src/system-update-generator/system-update-generator.c
index 794aa1a0c7..6c2f53774d 100644
--- a/src/system-update-generator/system-update-generator.c
+++ b/src/system-update-generator/system-update-generator.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include <unistd.h>
+#include "fs-util.h"
#include "log.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index fe4213c085..70871cf3e6 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -37,6 +37,7 @@
#include "sd-daemon.h"
#include "sd-login.h"
+#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-message.h"
@@ -51,25 +52,31 @@
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
+#include "glob-util.h"
#include "hostname-util.h"
#include "initreq.h"
#include "install.h"
#include "io-util.h"
#include "list.h"
+#include "locale-util.h"
#include "log.h"
#include "logs-show.h"
#include "macro.h"
#include "mkdir.h"
#include "pager.h"
+#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "set.h"
#include "signal-util.h"
#include "socket-util.h"
#include "spawn-ask-password-agent.h"
#include "spawn-polkit-agent.h"
#include "special.h"
+#include "stat-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "unit-name.h"
@@ -77,6 +84,7 @@
#include "util.h"
#include "utmp-wtmp.h"
#include "verbs.h"
+#include "virt.h"
static char **arg_types = NULL;
static char **arg_states = NULL;
@@ -288,6 +296,10 @@ static bool install_client_side(void) {
if (arg_scope == UNIT_FILE_GLOBAL)
return true;
+ /* Unsupported environment variable, mostly for debugging purposes */
+ if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
+ return true;
+
return false;
}
@@ -3478,7 +3490,8 @@ static void print_status_info(
dir = mfree(dir);
- if (path_get_parent(*dropin, &dir) < 0) {
+ dir = dirname_malloc(*dropin);
+ if (!dir) {
log_oom();
return;
}
@@ -5308,6 +5321,9 @@ static int enable_sysv_units(const char *verb, char **args) {
if (arg_scope != UNIT_FILE_SYSTEM)
return 0;
+ if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
+ return 0;
+
if (!STR_IN_SET(verb,
"enable",
"disable",
@@ -6615,6 +6631,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
{}
};
+ const char *p;
int c, r;
assert(argc >= 0);
@@ -6635,15 +6652,19 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
return version();
case 't': {
- const char *word, *state;
- size_t size;
+ if (isempty(optarg))
+ return log_error_errno(r, "--type requires arguments.");
- FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
- _cleanup_free_ char *type;
+ p = optarg;
+ for(;;) {
+ _cleanup_free_ char *type = NULL;
- type = strndup(word, size);
- if (!type)
- return -ENOMEM;
+ r = extract_first_word(&p, &type, ",", 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse type: %s", optarg);
+
+ if (r == 0)
+ break;
if (streq(type, "help")) {
help_types();
@@ -6684,18 +6705,21 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
if (!arg_properties)
return log_oom();
} else {
- const char *word, *state;
- size_t size;
+ p = optarg;
+ for(;;) {
+ _cleanup_free_ char *prop = NULL;
- FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
- char *prop;
+ r = extract_first_word(&p, &prop, ",", 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse property: %s", optarg);
- prop = strndup(word, size);
- if (!prop)
- return log_oom();
+ if (r == 0)
+ break;
- if (strv_consume(&arg_properties, prop) < 0)
+ if (strv_push(&arg_properties, prop) < 0)
return log_oom();
+
+ prop = NULL;
}
}
@@ -6861,15 +6885,19 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case ARG_STATE: {
- const char *word, *state;
- size_t size;
+ if (isempty(optarg))
+ return log_error_errno(r, "--signal requires arguments.");
- FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
+ p = optarg;
+ for(;;) {
_cleanup_free_ char *s = NULL;
- s = strndup(word, size);
- if (!s)
- return log_oom();
+ r = extract_first_word(&p, &s, ",", 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse signal: %s", optarg);
+
+ if (r == 0)
+ break;
if (streq(s, "help")) {
help_states();
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 177432bf9f..36d310b4c4 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -26,6 +26,7 @@
#include <shadow.h>
#include <utmp.h>
+#include "alloc-util.h"
#include "conf-files.h"
#include "copy.h"
#include "fileio-label.h"
@@ -1859,7 +1860,7 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
- lock = take_password_lock(arg_root);
+ lock = take_etc_passwd_lock(arg_root);
if (lock < 0) {
log_error_errno(lock, "Failed to take lock: %m");
goto finish;
diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
index 3374456973..b2d53d3b4f 100644
--- a/src/sysv-generator/sysv-generator.c
+++ b/src/sysv-generator/sysv-generator.c
@@ -25,8 +25,12 @@
#include <stdio.h>
#include <unistd.h>
+#include "alloc-util.h"
+#include "dirent-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "hashmap.h"
+#include "hexdecoct.h"
#include "install.h"
#include "log.h"
#include "mkdir.h"
@@ -34,6 +38,7 @@
#include "path-util.h"
#include "set.h"
#include "special.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
@@ -82,9 +87,13 @@ typedef struct SysvStub {
char **conflicts;
bool has_lsb;
bool reload;
+ bool loaded;
} SysvStub;
static void free_sysvstub(SysvStub *s) {
+ if (!s)
+ return;
+
free(s->name);
free(s->path);
free(s->description);
@@ -109,19 +118,14 @@ static void free_sysvstub_hashmapp(Hashmap **h) {
}
static int add_symlink(const char *service, const char *where) {
- _cleanup_free_ char *from = NULL, *to = NULL;
+ const char *from, *to;
int r;
assert(service);
assert(where);
- from = strjoin(arg_dest, "/", service, NULL);
- if (!from)
- return log_oom();
-
- to = strjoin(arg_dest, "/", where, ".wants/", service, NULL);
- if (!to)
- return log_oom();
+ from = strjoina(arg_dest, "/", service);
+ to = strjoina(arg_dest, "/", where, ".wants/", service);
mkdir_parents_label(to, 0755);
@@ -129,6 +133,7 @@ static int add_symlink(const char *service, const char *where) {
if (r < 0) {
if (errno == EEXIST)
return 0;
+
return -errno;
}
@@ -136,20 +141,19 @@ static int add_symlink(const char *service, const char *where) {
}
static int add_alias(const char *service, const char *alias) {
- _cleanup_free_ char *link = NULL;
+ const char *link;
int r;
assert(service);
assert(alias);
- link = strjoin(arg_dest, "/", alias, NULL);
- if (!link)
- return log_oom();
+ link = strjoina(arg_dest, "/", alias);
r = symlink(service, link);
if (r < 0) {
if (errno == EEXIST)
return 0;
+
return -errno;
}
@@ -157,26 +161,32 @@ static int add_alias(const char *service, const char *alias) {
}
static int generate_unit_file(SysvStub *s) {
- char **p;
+ _cleanup_free_ char *before = NULL, *after = NULL, *wants = NULL, *conflicts = NULL;
_cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *unit = NULL,
- *before = NULL, *after = NULL,
- *wants = NULL, *conflicts = NULL;
+ const char *unit;
+ char **p;
int r;
+ assert(s);
+
+ if (!s->loaded)
+ return 0;
+
+ unit = strjoina(arg_dest, "/", s->name);
+
before = strv_join(s->before, " ");
after = strv_join(s->after, " ");
wants = strv_join(s->wants, " ");
conflicts = strv_join(s->conflicts, " ");
- unit = strjoin(arg_dest, "/", s->name, NULL);
- if (!before || !after || !wants || !conflicts || !unit)
+
+ if (!before || !after || !wants || !conflicts)
return log_oom();
/* We might already have a symlink with the same name from a Provides:,
* or from backup files like /etc/init.d/foo.bak. Real scripts always win,
* so remove an existing link */
if (is_symlink(unit) > 0) {
- log_warning("Overwriting existing symlink %s with real service", unit);
+ log_warning("Overwriting existing symlink %s with real service.", unit);
(void) unlink(unit);
}
@@ -188,9 +198,11 @@ static int generate_unit_file(SysvStub *s) {
"# Automatically generated by systemd-sysv-generator\n\n"
"[Unit]\n"
"Documentation=man:systemd-sysv-generator(8)\n"
- "SourcePath=%s\n"
- "Description=%s\n",
- s->path, s->description);
+ "SourcePath=%s\n",
+ s->path);
+
+ if (s->description)
+ fprintf(f, "Description=%s\n", s->description);
if (!isempty(before))
fprintf(f, "Before=%s\n", before);
@@ -223,13 +235,17 @@ static int generate_unit_file(SysvStub *s) {
if (s->reload)
fprintf(f, "ExecReload=%s reload\n", s->path);
+ r = fflush_and_check(f);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write unit %s: %m", unit);
+
STRV_FOREACH(p, s->wanted_by) {
r = add_symlink(s->name, *p);
if (r < 0)
- log_error_errno(r, "Failed to create 'Wants' symlink to %s: %m", *p);
+ log_warning_errno(r, "Failed to create 'Wants' symlink to %s, ignoring: %m", *p);
}
- return 0;
+ return 1;
}
static bool usage_contains_reload(const char *line) {
@@ -259,7 +275,7 @@ static char *sysv_translate_name(const char *name) {
return res;
}
-static int sysv_translate_facility(const char *name, const char *filename, char **_r) {
+static int sysv_translate_facility(const char *name, const char *filename, char **ret) {
/* We silently ignore the $ prefix here. According to the LSB
* spec it simply indicates whether something is a
@@ -278,31 +294,45 @@ static int sysv_translate_facility(const char *name, const char *filename, char
"time", SPECIAL_TIME_SYNC_TARGET,
};
- char *filename_no_sh, *e, *r;
+ char *filename_no_sh, *e, *m;
const char *n;
unsigned i;
+ int r;
assert(name);
- assert(_r);
+ assert(filename);
+ assert(ret);
n = *name == '$' ? name + 1 : name;
for (i = 0; i < ELEMENTSOF(table); i += 2) {
-
if (!streq(table[i], n))
continue;
if (!table[i+1])
return 0;
- r = strdup(table[i+1]);
- if (!r)
+ m = strdup(table[i+1]);
+ if (!m)
return log_oom();
- goto finish;
+ *ret = m;
+ return 1;
+ }
+
+ /* If we don't know this name, fallback heuristics to figure
+ * out whether something is a target or a service alias. */
+
+ /* Facilities starting with $ are most likely targets */
+ if (*name == '$') {
+ r = unit_name_build(n, NULL, ".target", ret);
+ if (r < 0)
+ return log_error_errno(r, "Failed to build name: %m");
+
+ return r;
}
- /* strip ".sh" suffix from file name for comparison */
+ /* Strip ".sh" suffix from file name for comparison */
filename_no_sh = strdupa(filename);
e = endswith(filename_no_sh, ".sh");
if (e) {
@@ -310,103 +340,103 @@ static int sysv_translate_facility(const char *name, const char *filename, char
filename = filename_no_sh;
}
- /* If we don't know this name, fallback heuristics to figure
- * out whether something is a target or a service alias. */
-
- if (*name == '$') {
- int k;
-
- /* Facilities starting with $ are most likely targets */
- k = unit_name_build(n, NULL, ".target", &r);
- if (k < 0)
- return k;
-
- } else if (streq_ptr(n, filename))
- /* Names equaling the file name of the services are redundant */
+ /* Names equaling the file name of the services are redundant */
+ if (streq_ptr(n, filename))
return 0;
- else
- /* Everything else we assume to be normal service names */
- r = sysv_translate_name(n);
- if (!r)
- return -ENOMEM;
-finish:
- *_r = r;
+ /* Everything else we assume to be normal service names */
+ m = sysv_translate_name(n);
+ if (!m)
+ return log_oom();
+ *ret = m;
return 1;
}
static int handle_provides(SysvStub *s, unsigned line, const char *full_text, const char *text) {
- const char *word, *state_;
- size_t z;
int r;
- FOREACH_WORD_QUOTED(word, z, text, state_) {
- _cleanup_free_ char *n = NULL, *m = NULL;
- UnitType t;
+ assert(s);
+ assert(full_text);
+ assert(text);
- n = strndup(word, z);
- if (!n)
- return log_oom();
+ for (;;) {
+ _cleanup_free_ char *word = NULL, *m = NULL;
- r = sysv_translate_facility(n, basename(s->path), &m);
+ r = extract_first_word(&text, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to parse word from provides string: %m");
if (r == 0)
+ break;
+
+ r = sysv_translate_facility(word, basename(s->path), &m);
+ if (r <= 0) /* continue on error */
continue;
- t = unit_name_to_type(m);
- if (t == UNIT_SERVICE) {
+ switch (unit_name_to_type(m)) {
+
+ case UNIT_SERVICE:
log_debug("Adding Provides: alias '%s' for '%s'", m, s->name);
r = add_alias(s->name, m);
if (r < 0)
log_warning_errno(r, "[%s:%u] Failed to add LSB Provides name %s, ignoring: %m", s->path, line, m);
- } else if (t == UNIT_TARGET) {
+ break;
+
+ case UNIT_TARGET:
+
/* NB: SysV targets which are provided by a
* service are pulled in by the services, as
* an indication that the generic service is
* now available. This is strictly one-way.
* The targets do NOT pull in SysV services! */
+
r = strv_extend(&s->before, m);
if (r < 0)
return log_oom();
+
r = strv_extend(&s->wants, m);
if (r < 0)
return log_oom();
+
if (streq(m, SPECIAL_NETWORK_ONLINE_TARGET)) {
r = strv_extend(&s->before, SPECIAL_NETWORK_TARGET);
if (r < 0)
return log_oom();
}
- } else if (t == _UNIT_TYPE_INVALID)
+
+ break;
+
+ case _UNIT_TYPE_INVALID:
log_warning("Unit name '%s' is invalid", m);
- else
+ break;
+
+ default:
log_warning("Unknown unit type for unit '%s'", m);
+ }
}
- if (!isempty(state_))
- log_error("[%s:%u] Trailing garbage in Provides, ignoring.", s->path, line);
+
return 0;
}
static int handle_dependencies(SysvStub *s, unsigned line, const char *full_text, const char *text) {
- const char *word, *state_;
- size_t z;
int r;
- FOREACH_WORD_QUOTED(word, z, text, state_) {
- _cleanup_free_ char *n = NULL, *m = NULL;
- bool is_before;
+ assert(s);
+ assert(full_text);
+ assert(text);
- n = strndup(word, z);
- if (!n)
- return log_oom();
+ for (;;) {
+ _cleanup_free_ char *word = NULL, *m = NULL;
+ bool is_before;
- r = sysv_translate_facility(n, basename(s->path), &m);
- if (r < 0) {
- log_warning_errno(r, "[%s:%u] Failed to translate LSB dependency %s, ignoring: %m", s->path, line, n);
- continue;
- }
+ r = extract_first_word(&text, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse word from provides string: %m");
if (r == 0)
+ break;
+
+ r = sysv_translate_facility(word, basename(s->path), &m);
+ if (r <= 0) /* continue on error */
continue;
is_before = startswith_no_case(full_text, "X-Start-Before:");
@@ -416,15 +446,14 @@ static int handle_dependencies(SysvStub *s, unsigned line, const char *full_text
r = strv_extend(&s->after, m);
if (r < 0)
return log_oom();
+
r = strv_extend(&s->wants, m);
} else
r = strv_extend(is_before ? &s->before : &s->after, m);
-
if (r < 0)
return log_oom();
}
- if (!isempty(state_))
- log_warning("[%s:%u] Trailing garbage in %*s, ignoring.", s->path, line, (int)(strchr(full_text, ':') - full_text), full_text);
+
return 0;
}
@@ -442,24 +471,22 @@ static int load_sysv(SysvStub *s) {
_cleanup_free_ char *short_description = NULL, *long_description = NULL, *chkconfig_description = NULL;
char *description;
bool supports_reload = false;
+ char l[LINE_MAX];
assert(s);
f = fopen(s->path, "re");
- if (!f)
- return errno == ENOENT ? 0 : -errno;
+ if (!f) {
+ if (errno == ENOENT)
+ return 0;
- log_debug("Loading SysV script %s", s->path);
+ return log_error_errno(errno, "Failed to open %s: %m", s->path);
+ }
- while (!feof(f)) {
- char l[LINE_MAX], *t;
+ log_debug("Loading SysV script %s", s->path);
- if (!fgets(l, sizeof(l), f)) {
- if (feof(f))
- break;
-
- return log_error_errno(errno, "Failed to read configuration file '%s': %m", s->path);
- }
+ FOREACH_LINE(l, f, goto fail) {
+ char *t;
line++;
@@ -502,29 +529,25 @@ static int load_sysv(SysvStub *s) {
if (startswith_no_case(t, "description:")) {
- size_t k = strlen(t);
- char *d;
- const char *j;
+ size_t k;
+ const const char *j;
- if (t[k-1] == '\\') {
+ k = strlen(t);
+ if (k > 0 && t[k-1] == '\\') {
state = DESCRIPTION;
t[k-1] = 0;
}
j = strstrip(t+12);
- if (j && *j) {
- d = strdup(j);
- if (!d)
- return -ENOMEM;
- } else
- d = NULL;
+ if (isempty(j))
+ j = NULL;
- free(chkconfig_description);
- chkconfig_description = d;
+ r = free_and_strdup(&chkconfig_description, j);
+ if (r < 0)
+ return log_oom();
} else if (startswith_no_case(t, "pidfile:")) {
-
- char *fn;
+ const char *fn;
state = NORMAL;
@@ -534,12 +557,9 @@ static int load_sysv(SysvStub *s) {
continue;
}
- fn = strdup(fn);
- if (!fn)
- return -ENOMEM;
-
- free(s->pid_file);
- s->pid_file = fn;
+ r = free_and_strdup(&s->pid_file, fn);
+ if (r < 0)
+ return log_oom();
}
} else if (state == DESCRIPTION) {
@@ -547,25 +567,25 @@ static int load_sysv(SysvStub *s) {
/* Try to parse Red Hat style description
* continuation */
- size_t k = strlen(t);
+ size_t k;
char *j;
- if (t[k-1] == '\\')
+ k = strlen(t);
+ if (k > 0 && t[k-1] == '\\')
t[k-1] = 0;
else
state = NORMAL;
j = strstrip(t);
- if (j && *j) {
+ if (!isempty(j)) {
char *d = NULL;
if (chkconfig_description)
d = strjoin(chkconfig_description, " ", j, NULL);
else
d = strdup(j);
-
if (!d)
- return -ENOMEM;
+ return log_oom();
free(chkconfig_description);
chkconfig_description = d;
@@ -579,6 +599,7 @@ static int load_sysv(SysvStub *s) {
r = handle_provides(s, line, t, t + 9);
if (r < 0)
return r;
+
} else if (startswith_no_case(t, "Required-Start:") ||
startswith_no_case(t, "Should-Start:") ||
startswith_no_case(t, "X-Start-Before:") ||
@@ -590,55 +611,47 @@ static int load_sysv(SysvStub *s) {
if (r < 0)
return r;
-
} else if (startswith_no_case(t, "Description:")) {
- char *d, *j;
+ const char *j;
state = LSB_DESCRIPTION;
j = strstrip(t+12);
- if (j && *j) {
- d = strdup(j);
- if (!d)
- return -ENOMEM;
- } else
- d = NULL;
+ if (isempty(j))
+ j = NULL;
- free(long_description);
- long_description = d;
+ r = free_and_strdup(&long_description, j);
+ if (r < 0)
+ return log_oom();
} else if (startswith_no_case(t, "Short-Description:")) {
- char *d, *j;
+ const char *j;
state = LSB;
j = strstrip(t+18);
- if (j && *j) {
- d = strdup(j);
- if (!d)
- return -ENOMEM;
- } else
- d = NULL;
+ if (isempty(j))
+ j = NULL;
- free(short_description);
- short_description = d;
+ r = free_and_strdup(&short_description, j);
+ if (r < 0)
+ return log_oom();
} else if (state == LSB_DESCRIPTION) {
if (startswith(l, "#\t") || startswith(l, "# ")) {
- char *j;
+ const char *j;
j = strstrip(t);
- if (j && *j) {
+ if (!isempty(j)) {
char *d = NULL;
if (long_description)
d = strjoin(long_description, " ", t, NULL);
else
d = strdup(j);
-
if (!d)
- return -ENOMEM;
+ return log_oom();
free(long_description);
long_description = d;
@@ -669,12 +682,16 @@ static int load_sysv(SysvStub *s) {
d = strappend(s->has_lsb ? "LSB: " : "SYSV: ", description);
if (!d)
- return -ENOMEM;
+ return log_oom();
s->description = d;
}
+ s->loaded = true;
return 0;
+
+fail:
+ return log_error_errno(errno, "Failed to read configuration file '%s': %m", s->path);
}
static int fix_order(SysvStub *s, Hashmap *all_services) {
@@ -684,6 +701,9 @@ static int fix_order(SysvStub *s, Hashmap *all_services) {
assert(s);
+ if (!s->loaded)
+ return 0;
+
if (s->sysv_start_priority < 0)
return 0;
@@ -691,6 +711,9 @@ static int fix_order(SysvStub *s, Hashmap *all_services) {
if (s == other)
continue;
+ if (!other->loaded)
+ continue;
+
if (other->sysv_start_priority < 0)
continue;
@@ -703,13 +726,12 @@ static int fix_order(SysvStub *s, Hashmap *all_services) {
r = strv_extend(&s->after, other->name);
if (r < 0)
return log_oom();
- }
- else if (other->sysv_start_priority > s->sysv_start_priority) {
+
+ } else if (other->sysv_start_priority > s->sysv_start_priority) {
r = strv_extend(&s->before, other->name);
if (r < 0)
return log_oom();
- }
- else
+ } else
continue;
/* FIXME: Maybe we should compare the name here lexicographically? */
@@ -721,6 +743,9 @@ static int fix_order(SysvStub *s, Hashmap *all_services) {
static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
char **path;
+ assert(lp);
+ assert(all_services);
+
STRV_FOREACH(path, lp->sysvinit_path) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
@@ -728,21 +753,18 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
d = opendir(*path);
if (!d) {
if (errno != ENOENT)
- log_warning_errno(errno, "opendir(%s) failed: %m", *path);
+ log_warning_errno(errno, "Opening %s failed, ignoring: %m", *path);
continue;
}
- while ((de = readdir(d))) {
+ FOREACH_DIRENT(de, d, log_error_errno(errno, "Failed to enumerate directory %s, ignoring: %m", *path)) {
_cleanup_free_ char *fpath = NULL, *name = NULL;
_cleanup_(free_sysvstubp) SysvStub *service = NULL;
struct stat st;
int r;
- if (hidden_file(de->d_name))
- continue;
-
if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) {
- log_warning_errno(errno, "stat() failed on %s/%s: %m", *path, de->d_name);
+ log_warning_errno(errno, "stat() failed on %s/%s, ignoring: %m", *path, de->d_name);
continue;
}
@@ -759,15 +781,15 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
if (hashmap_contains(all_services, name))
continue;
- fpath = strjoin(*path, "/", de->d_name, NULL);
- if (!fpath)
- return log_oom();
-
if (unit_file_lookup_state(UNIT_FILE_SYSTEM, NULL, lp, name) >= 0) {
log_debug("Native unit for %s already exists, skipping", name);
continue;
}
+ fpath = strjoin(*path, "/", de->d_name, NULL);
+ if (!fpath)
+ return log_oom();
+
service = new0(SysvStub, 1);
if (!service)
return log_oom();
@@ -775,12 +797,12 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
service->sysv_start_priority = -1;
service->name = name;
service->path = fpath;
+ name = fpath = NULL;
r = hashmap_put(all_services, service->name, service);
if (r < 0)
return log_oom();
- name = fpath = NULL;
service = NULL;
}
}
@@ -789,43 +811,41 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
}
static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_services) {
- char **p;
- unsigned i;
- _cleanup_closedir_ DIR *d = NULL;
- _cleanup_free_ char *path = NULL, *fpath = NULL;
- SysvStub *service;
- Iterator j;
Set *runlevel_services[ELEMENTSOF(rcnd_table)] = {};
_cleanup_set_free_ Set *shutdown_services = NULL;
- int r = 0;
+ SysvStub *service;
+ unsigned i;
+ Iterator j;
+ char **p;
+ int r;
- STRV_FOREACH(p, lp->sysvrcnd_path)
+ assert(lp);
+
+ STRV_FOREACH(p, lp->sysvrcnd_path) {
for (i = 0; i < ELEMENTSOF(rcnd_table); i ++) {
+
+ _cleanup_closedir_ DIR *d = NULL;
+ _cleanup_free_ char *path = NULL;
struct dirent *de;
- free(path);
path = strjoin(*p, "/", rcnd_table[i].path, NULL);
- if (!path)
- return -ENOMEM;
-
- safe_closedir(d);
+ if (!path) {
+ r = log_oom();
+ goto finish;
+ }
d = opendir(path);
if (!d) {
if (errno != ENOENT)
- log_warning_errno(errno, "opendir(%s) failed: %m", path);
+ log_warning_errno(errno, "Opening %s failed, ignoring: %m", path);
continue;
}
- while ((de = readdir(d))) {
- _cleanup_free_ char *name = NULL;
-
+ FOREACH_DIRENT(de, d, log_error_errno(errno, "Failed to enumerate directory %s, ignoring: %m", path)) {
+ _cleanup_free_ char *name = NULL, *fpath = NULL;
int a, b;
- if (hidden_file(de->d_name))
- continue;
-
if (de->d_name[0] != 'S' && de->d_name[0] != 'K')
continue;
@@ -838,10 +858,9 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic
if (a < 0 || b < 0)
continue;
- free(fpath);
fpath = strjoin(*p, "/", de->d_name, NULL);
if (!fpath) {
- r = -ENOMEM;
+ r = log_oom();
goto finish;
}
@@ -853,64 +872,77 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic
service = hashmap_get(all_services, name);
if (!service){
- log_debug("Ignoring %s symlink in %s, not generating %s.",
- de->d_name, rcnd_table[i].path, name);
+ log_debug("Ignoring %s symlink in %s, not generating %s.", de->d_name, rcnd_table[i].path, name);
continue;
}
if (de->d_name[0] == 'S') {
- if (rcnd_table[i].type == RUNLEVEL_UP) {
- service->sysv_start_priority =
- MAX(a*10 + b, service->sysv_start_priority);
- }
+ if (rcnd_table[i].type == RUNLEVEL_UP)
+ service->sysv_start_priority = MAX(a*10 + b, service->sysv_start_priority);
r = set_ensure_allocated(&runlevel_services[i], NULL);
- if (r < 0)
+ if (r < 0) {
+ log_oom();
goto finish;
+ }
r = set_put(runlevel_services[i], service);
- if (r < 0)
+ if (r < 0) {
+ log_oom();
goto finish;
+ }
} else if (de->d_name[0] == 'K' &&
(rcnd_table[i].type == RUNLEVEL_DOWN)) {
r = set_ensure_allocated(&shutdown_services, NULL);
- if (r < 0)
+ if (r < 0) {
+ log_oom();
goto finish;
+ }
r = set_put(shutdown_services, service);
- if (r < 0)
+ if (r < 0) {
+ log_oom();
goto finish;
+ }
}
}
}
+ }
for (i = 0; i < ELEMENTSOF(rcnd_table); i ++)
SET_FOREACH(service, runlevel_services[i], j) {
r = strv_extend(&service->before, rcnd_table[i].target);
- if (r < 0)
- return log_oom();
+ if (r < 0) {
+ log_oom();
+ goto finish;
+ }
r = strv_extend(&service->wanted_by, rcnd_table[i].target);
- if (r < 0)
- return log_oom();
+ if (r < 0) {
+ log_oom();
+ goto finish;
+ }
}
SET_FOREACH(service, shutdown_services, j) {
r = strv_extend(&service->before, SPECIAL_SHUTDOWN_TARGET);
- if (r < 0)
- return log_oom();
+ if (r < 0) {
+ log_oom();
+ goto finish;
+ }
r = strv_extend(&service->conflicts, SPECIAL_SHUTDOWN_TARGET);
- if (r < 0)
- return log_oom();
+ if (r < 0) {
+ log_oom();
+ goto finish;
+ }
}
r = 0;
finish:
-
for (i = 0; i < ELEMENTSOF(rcnd_table); i++)
set_free(runlevel_services[i]);
@@ -918,11 +950,11 @@ finish:
}
int main(int argc, char *argv[]) {
- int r, q;
- _cleanup_lookup_paths_free_ LookupPaths lp = {};
_cleanup_(free_sysvstub_hashmapp) Hashmap *all_services = NULL;
+ _cleanup_lookup_paths_free_ LookupPaths lp = {};
SysvStub *service;
Iterator j;
+ int r;
if (argc > 1 && argc != 4) {
log_error("This program takes three or no arguments.");
@@ -940,43 +972,34 @@ int main(int argc, char *argv[]) {
r = lookup_paths_init(&lp, MANAGER_SYSTEM, true, NULL, NULL, NULL, NULL);
if (r < 0) {
- log_error("Failed to find lookup paths.");
- return EXIT_FAILURE;
+ log_error_errno(r, "Failed to find lookup paths: %m");
+ goto finish;
}
all_services = hashmap_new(&string_hash_ops);
if (!all_services) {
- log_oom();
- return EXIT_FAILURE;
+ r = log_oom();
+ goto finish;
}
r = enumerate_sysv(&lp, all_services);
- if (r < 0) {
- log_error("Failed to generate units for all init scripts.");
- return EXIT_FAILURE;
- }
+ if (r < 0)
+ goto finish;
r = set_dependencies_from_rcnd(&lp, all_services);
- if (r < 0) {
- log_error("Failed to read runlevels from rcnd links.");
- return EXIT_FAILURE;
- }
+ if (r < 0)
+ goto finish;
- HASHMAP_FOREACH(service, all_services, j) {
- q = load_sysv(service);
- if (q < 0)
- continue;
- }
+ HASHMAP_FOREACH(service, all_services, j)
+ (void) load_sysv(service);
HASHMAP_FOREACH(service, all_services, j) {
- q = fix_order(service, all_services);
- if (q < 0)
- continue;
-
- q = generate_unit_file(service);
- if (q < 0)
- continue;
+ (void) fix_order(service, all_services);
+ (void) generate_unit_file(service);
}
- return EXIT_SUCCESS;
+ r = 0;
+
+finish:
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/test/test-async.c b/src/test/test-async.c
index abd36d693c..ada6d67c42 100644
--- a/src/test/test-async.c
+++ b/src/test/test-async.c
@@ -20,8 +20,9 @@
#include <unistd.h>
#include "async.h"
-#include "util.h"
+#include "fileio.h"
#include "macro.h"
+#include "util.h"
static bool test_async = false;
diff --git a/src/test/test-btrfs.c b/src/test/test-btrfs.c
index afe3ff8fc2..33356f8387 100644
--- a/src/test/test-btrfs.c
+++ b/src/test/test-btrfs.c
@@ -25,6 +25,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "log.h"
+#include "parse-util.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
index 12f366a34c..70819b0371 100644
--- a/src/test/test-calendarspec.c
+++ b/src/test/test-calendarspec.c
@@ -21,6 +21,7 @@
#include <string.h>
+#include "alloc-util.h"
#include "calendarspec.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/test/test-cap-list.c b/src/test/test-cap-list.c
index 43a2d35b80..4418bafda6 100644
--- a/src/test/test-cap-list.c
+++ b/src/test/test-cap-list.c
@@ -19,12 +19,15 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "fileio.h"
-#include "cap-list.h"
-#include "capability.h"
#include <sys/prctl.h>
+#include "alloc-util.h"
+#include "cap-list.h"
+#include "capability-util.h"
+#include "fileio.h"
+#include "parse-util.h"
+#include "util.h"
+
/* verify the capability parser */
static void test_cap_list(void) {
int i;
diff --git a/src/test/test-capability.c b/src/test/test-capability.c
index 09d7e61e92..fc8d3ffe0d 100644
--- a/src/test/test-capability.c
+++ b/src/test/test-capability.c
@@ -24,7 +24,7 @@
#include <sys/wait.h>
#include <unistd.h>
-#include "capability.h"
+#include "capability-util.h"
#include "fd-util.h"
#include "macro.h"
#include "util.h"
diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c
index 7bf59a0aa2..a48b324e26 100644
--- a/src/test/test-cgroup-util.c
+++ b/src/test/test-cgroup-util.c
@@ -19,12 +19,16 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "cgroup-util.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "formats-util.h"
+#include "parse-util.h"
#include "process-util.h"
#include "string-util.h"
#include "test-helper.h"
+#include "user-util.h"
#include "util.h"
static void check_p_d_u(const char *path, int code, const char *result) {
diff --git a/src/test/test-condition.c b/src/test/test-condition.c
index 91a27138eb..f224c6cdd8 100644
--- a/src/test/test-condition.c
+++ b/src/test/test-condition.c
@@ -19,9 +19,10 @@
#include "sd-id128.h"
+#include "alloc-util.h"
#include "apparmor-util.h"
#include "architecture.h"
-#include "audit.h"
+#include "audit-util.h"
#include "condition.h"
#include "hostname-util.h"
#include "ima-util.h"
diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c
index 30ba5364c4..a69698d4ea 100644
--- a/src/test/test-conf-files.c
+++ b/src/test/test-conf-files.c
@@ -22,11 +22,14 @@
#include <stdarg.h>
#include <stdio.h>
+#include "alloc-util.h"
#include "conf-files.h"
+#include "fs-util.h"
#include "macro.h"
#include "rm-rf.h"
#include "string-util.h"
#include "strv.h"
+#include "user-util.h"
#include "util.h"
static void setup_test_dir(char *tmp_dir, const char *files, ...) {
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index 1bd50edca2..ad57cb0202 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -19,9 +19,11 @@
#include <unistd.h>
+#include "alloc-util.h"
#include "copy.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "macro.h"
#include "mkdir.h"
#include "path-util.h"
diff --git a/src/test/test-date.c b/src/test/test-date.c
index e1c6ecb2ef..c6d8bf82ea 100644
--- a/src/test/test-date.c
+++ b/src/test/test-date.c
@@ -21,8 +21,9 @@
#include <string.h>
-#include "util.h"
+#include "alloc-util.h"
#include "string-util.h"
+#include "util.h"
static void test_should_pass(const char *p) {
usec_t t, q;
diff --git a/src/test/test-device-nodes.c b/src/test/test-device-nodes.c
index 1c745d6e5b..646b168cc0 100644
--- a/src/test/test-device-nodes.c
+++ b/src/test/test-device-nodes.c
@@ -21,6 +21,7 @@
#include <sys/types.h>
+#include "alloc-util.h"
#include "device-nodes.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c
index 1a8541e1cc..d5778748a0 100644
--- a/src/test/test-dns-domain.c
+++ b/src/test/test-dns-domain.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "dns-domain.h"
#include "macro.h"
#include "string-util.h"
diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c
index 033d5af719..c597d5aecd 100644
--- a/src/test/test-ellipsize.c
+++ b/src/test/test-ellipsize.c
@@ -21,6 +21,7 @@
#include <stdio.h>
+#include "alloc-util.h"
#include "def.h"
#include "string-util.h"
#include "terminal-util.h"
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index fa6336f1fb..e2ec53ee51 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -17,14 +17,20 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <grp.h>
+#include <pwd.h>
#include <stdio.h>
+#include <sys/types.h>
-#include "unit.h"
-#include "manager.h"
-#include "util.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "macro.h"
+#include "manager.h"
#include "mkdir.h"
+#include "path-util.h"
#include "rm-rf.h"
+#include "unit.h"
+#include "util.h"
typedef void (*test_function_t)(Manager *m);
@@ -123,11 +129,17 @@ static void test_exec_systemcallerrornumber(Manager *m) {
}
static void test_exec_user(Manager *m) {
- test(m, "exec-user.service", 0, CLD_EXITED);
+ if (getpwnam("nobody"))
+ test(m, "exec-user.service", 0, CLD_EXITED);
+ else
+ log_error_errno(errno, "Skipping test_exec_user, could not find nobody user: %m");
}
static void test_exec_group(Manager *m) {
- test(m, "exec-group.service", 0, CLD_EXITED);
+ if (getgrnam("nobody"))
+ test(m, "exec-group.service", 0, CLD_EXITED);
+ else
+ log_error_errno(errno, "Skipping test_exec_group, could not find nobody group: %m");
}
static void test_exec_environment(Manager *m) {
@@ -136,6 +148,26 @@ static void test_exec_environment(Manager *m) {
test(m, "exec-environment-empty.service", 0, CLD_EXITED);
}
+static void test_exec_environmentfile(Manager *m) {
+ static const char e[] =
+ "VAR1='word1 word2'\n"
+ "VAR2=word3 \n"
+ "# comment1\n"
+ "\n"
+ "; comment2\n"
+ " ; # comment3\n"
+ "line without an equal\n"
+ "VAR3='$word 5 6'\n";
+ int r;
+
+ r = write_string_file("/tmp/test-exec_environmentfile.conf", e, WRITE_STRING_FILE_CREATE);
+ assert_se(r == 0);
+
+ test(m, "exec-environmentfile.service", 0, CLD_EXITED);
+
+ unlink("/tmp/test-exec_environmentfile.conf");
+}
+
static void test_exec_umask(Manager *m) {
test(m, "exec-umask-default.service", 0, CLD_EXITED);
test(m, "exec-umask-0177.service", 0, CLD_EXITED);
@@ -144,7 +176,51 @@ static void test_exec_umask(Manager *m) {
static void test_exec_runtimedirectory(Manager *m) {
test(m, "exec-runtimedirectory.service", 0, CLD_EXITED);
test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
- test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
+ if (getgrnam("nobody"))
+ test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
+ else
+ log_error_errno(errno, "Skipping test_exec_runtimedirectory-owner, could not find nobody group: %m");
+}
+
+static void test_exec_capabilityboundingset(Manager *m) {
+ int r;
+
+ /* We use capsh to test if the capabilities are
+ * properly set, so be sure that it exists */
+ r = find_binary("capsh", NULL);
+ if (r < 0) {
+ log_error_errno(r, "Skipping test_exec_capabilityboundingset, could not find capsh binary: %m");
+ return;
+ }
+
+ test(m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
+}
+
+static void test_exec_privatenetwork(Manager *m) {
+ int r;
+
+ r = find_binary("ip", NULL);
+ if (r < 0) {
+ log_error_errno(r, "Skipping test_exec_privatenetwork, could not find ip binary: %m");
+ return;
+ }
+
+ test(m, "exec-privatenetwork-yes.service", 0, CLD_EXITED);
+}
+
+static void test_exec_oomscoreadjust(Manager *m) {
+ test(m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED);
+ test(m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED);
+}
+
+static void test_exec_ioschedulingclass(Manager *m) {
+ test(m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED);
+ test(m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED);
+ test(m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED);
+ test(m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED);
}
int main(int argc, char *argv[]) {
@@ -154,13 +230,18 @@ int main(int argc, char *argv[]) {
test_exec_ignoresigpipe,
test_exec_privatetmp,
test_exec_privatedevices,
+ test_exec_privatenetwork,
test_exec_systemcallfilter,
test_exec_systemcallerrornumber,
test_exec_user,
test_exec_group,
test_exec_environment,
+ test_exec_environmentfile,
test_exec_umask,
test_exec_runtimedirectory,
+ test_exec_capabilityboundingset,
+ test_exec_oomscoreadjust,
+ test_exec_ioschedulingclass,
NULL,
};
test_function_t *test = NULL;
@@ -177,7 +258,7 @@ int main(int argc, char *argv[]) {
}
assert_se(setenv("XDG_RUNTIME_DIR", "/tmp/", 1) == 0);
- assert_se(set_unit_path(TEST_DIR) >= 0);
+ assert_se(set_unit_path(TEST_DIR "/test-execute/") >= 0);
r = manager_new(MANAGER_USER, true, &m);
if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT)) {
diff --git a/src/test/test-extract-word.c b/src/test/test-extract-word.c
new file mode 100644
index 0000000000..09698c07c7
--- /dev/null
+++ b/src/test/test-extract-word.c
@@ -0,0 +1,546 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+ Copyright 2013 Thomas H.P. Andersen
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "extract-word.h"
+#include "log.h"
+#include "string-util.h"
+
+static void test_extract_first_word(void) {
+ const char *p, *original;
+ char *t;
+
+ p = original = "foobar waldo";
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "foobar"));
+ free(t);
+ assert_se(p == original + 7);
+
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word(&p, &t, NULL, 0) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "\"foobar\" \'waldo\'";
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "\"foobar\""));
+ free(t);
+ assert_se(p == original + 9);
+
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "\'waldo\'"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word(&p, &t, NULL, 0) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "\"foobar\" \'waldo\'";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(streq(t, "foobar"));
+ free(t);
+ assert_se(p == original + 9);
+
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word(&p, &t, NULL, 0) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "\"";
+ assert_se(extract_first_word(&p, &t, NULL, 0) == 1);
+ assert_se(streq(t, "\""));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\"";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
+ assert_se(p == original + 1);
+
+ p = original = "\'";
+ assert_se(extract_first_word(&p, &t, NULL, 0) == 1);
+ assert_se(streq(t, "\'"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\'";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
+ assert_se(p == original + 1);
+
+ p = original = "\'fooo";
+ assert_se(extract_first_word(&p, &t, NULL, 0) == 1);
+ assert_se(streq(t, "\'fooo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\'fooo";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "\'fooo";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "fooo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\"fooo";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "fooo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "yay\'foo\'bar";
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "yay\'foo\'bar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "yay\'foo\'bar";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(streq(t, "yayfoobar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " foobar ";
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "foobar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " foo\\ba\\x6ar ";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0);
+ assert_se(streq(t, "foo\ba\x6ar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " foo\\ba\\x6ar ";
+ assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
+ assert_se(streq(t, "foobax6ar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " f\\u00f6o \"pi\\U0001F4A9le\" ";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0);
+ assert_se(streq(t, "föo"));
+ free(t);
+ assert_se(p == original + 13);
+
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE) > 0);
+ assert_se(streq(t, "pi\360\237\222\251le"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "fooo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0);
+ assert_se(streq(t, "fooo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "fooo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
+ assert_se(streq(t, "fooo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word(&p, &t, NULL, 0) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "foo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "foo::bar";
+ assert_se(extract_first_word(&p, &t, ":", 0) == 1);
+ assert_se(streq(t, "foo"));
+ free(t);
+ assert_se(p == original + 5);
+
+ assert_se(extract_first_word(&p, &t, ":", 0) == 1);
+ assert_se(streq(t, "bar"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word(&p, &t, ":", 0) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "foo\\:bar::waldo";
+ assert_se(extract_first_word(&p, &t, ":", 0) == 1);
+ assert_se(streq(t, "foo:bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ assert_se(extract_first_word(&p, &t, ":", 0) == 1);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word(&p, &t, ":", 0) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "foo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "foo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "fooo bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0);
+ assert_se(streq(t, "fooo bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
+ assert_se(streq(t, "fooo bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
+ assert_se(streq(t, "fooo\\ bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "\\w+@\\K[\\d.]+";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL);
+ assert_se(p == original + 1);
+
+ p = original = "\\w+@\\K[\\d.]+";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
+ assert_se(streq(t, "\\w+@\\K[\\d.]+"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\\w+\\b";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
+ assert_se(streq(t, "\\w+\b"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "-N ''";
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(streq(t, "-N"));
+ free(t);
+ assert_se(p == original + 3);
+
+ assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
+ assert_se(streq(t, ""));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = ":foo\\:bar::waldo:";
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(t);
+ assert_se(streq(t, ""));
+ free(t);
+ assert_se(p == original + 1);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(streq(t, "foo:bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(t);
+ assert_se(streq(t, ""));
+ free(t);
+ assert_se(p == original + 11);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(p == original + 17);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
+ assert_se(streq(t, ""));
+ free(t);
+ assert_se(p == NULL);
+
+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 0);
+ assert_se(!t);
+ assert_se(!p);
+}
+
+static void test_extract_first_word_and_warn(void) {
+ const char *p, *original;
+ char *t;
+
+ p = original = "foobar waldo";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "foobar"));
+ free(t);
+ assert_se(p == original + 7);
+
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "\"foobar\" \'waldo\'";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "foobar"));
+ free(t);
+ assert_se(p == original + 9);
+
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "waldo"));
+ free(t);
+ assert_se(isempty(p));
+
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0);
+ assert_se(!t);
+ assert_se(isempty(p));
+
+ p = original = "\"";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(p == original + 1);
+
+ p = original = "\'";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(p == original + 1);
+
+ p = original = "\'fooo";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "\'fooo";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " foo\\ba\\x6ar ";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "foo\ba\x6ar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " foo\\ba\\x6ar ";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "foobax6ar"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = " f\\u00f6o \"pi\\U0001F4A9le\" ";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "föo"));
+ free(t);
+ assert_se(p == original + 13);
+
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "pi\360\237\222\251le"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo\\"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "foo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) == -EINVAL);
+ assert_se(p == original + 5);
+
+ p = original = "\"foo\\";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "foo"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "fooo\\ bar quux";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "fooo\\ bar"));
+ free(t);
+ assert_se(p == original + 10);
+
+ p = original = "\\w+@\\K[\\d.]+";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "\\w+@\\K[\\d.]+"));
+ free(t);
+ assert_se(isempty(p));
+
+ p = original = "\\w+\\b";
+ assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
+ assert_se(streq(t, "\\w+\b"));
+ free(t);
+ assert_se(isempty(p));
+}
+
+static void test_extract_many_words(void) {
+ const char *p, *original;
+ char *a, *b, *c;
+
+ p = original = "foobar waldi piep";
+ assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 3);
+ assert_se(isempty(p));
+ assert_se(streq_ptr(a, "foobar"));
+ assert_se(streq_ptr(b, "waldi"));
+ assert_se(streq_ptr(c, "piep"));
+ free(a);
+ free(b);
+ free(c);
+
+ p = original = "'foobar' wa\"ld\"i ";
+ assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 2);
+ assert_se(isempty(p));
+ assert_se(streq_ptr(a, "'foobar'"));
+ assert_se(streq_ptr(b, "wa\"ld\"i"));
+ assert_se(streq_ptr(c, NULL));
+ free(a);
+ free(b);
+
+ p = original = "'foobar' wa\"ld\"i ";
+ assert_se(extract_many_words(&p, NULL, EXTRACT_QUOTES, &a, &b, &c, NULL) == 2);
+ assert_se(isempty(p));
+ assert_se(streq_ptr(a, "foobar"));
+ assert_se(streq_ptr(b, "waldi"));
+ assert_se(streq_ptr(c, NULL));
+ free(a);
+ free(b);
+
+ p = original = "";
+ assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0);
+ assert_se(isempty(p));
+ assert_se(streq_ptr(a, NULL));
+ assert_se(streq_ptr(b, NULL));
+ assert_se(streq_ptr(c, NULL));
+
+ p = original = " ";
+ assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0);
+ assert_se(isempty(p));
+ assert_se(streq_ptr(a, NULL));
+ assert_se(streq_ptr(b, NULL));
+ assert_se(streq_ptr(c, NULL));
+
+ p = original = "foobar";
+ assert_se(extract_many_words(&p, NULL, 0, NULL) == 0);
+ assert_se(p == original);
+
+ p = original = "foobar waldi";
+ assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1);
+ assert_se(p == original+7);
+ assert_se(streq_ptr(a, "foobar"));
+ free(a);
+
+ p = original = " foobar ";
+ assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1);
+ assert_se(isempty(p));
+ assert_se(streq_ptr(a, "foobar"));
+ free(a);
+}
+
+int main(int argc, char *argv[]) {
+ log_parse_environment();
+ log_open();
+
+ test_extract_first_word();
+ test_extract_first_word_and_warn();
+ test_extract_many_words();
+
+ return 0;
+}
diff --git a/src/test/test-fdset.c b/src/test/test-fdset.c
index 96d5e38177..282aab1246 100644
--- a/src/test/test-fdset.c
+++ b/src/test/test-fdset.c
@@ -22,6 +22,7 @@
#include "fd-util.h"
#include "fdset.h"
+#include "fileio.h"
#include "macro.h"
#include "util.h"
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index a40f013491..e588681b86 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -23,11 +23,13 @@
#include <fcntl.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "ctype.h"
#include "def.h"
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "parse-util.h"
#include "process-util.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c
index b02f3a6e7c..27816ac779 100644
--- a/src/test/test-fstab-util.c
+++ b/src/test/test-fstab-util.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "fstab-util.h"
#include "log.h"
#include "string-util.h"
diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c
index 2da6446961..6bf33306a9 100644
--- a/src/test/test-hashmap-plain.c
+++ b/src/test/test-hashmap-plain.c
@@ -17,6 +17,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "hashmap.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/test/test-hostname-util.c b/src/test/test-hostname-util.c
index ac8f4ecc68..590175433c 100644
--- a/src/test/test-hostname-util.c
+++ b/src/test/test-hostname-util.c
@@ -21,10 +21,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
+#include "alloc-util.h"
#include "fileio.h"
#include "hostname-util.h"
#include "string-util.h"
+#include "util.h"
static void test_hostname_is_valid(void) {
assert_se(hostname_is_valid("foobar", false));
diff --git a/src/test/test-id128.c b/src/test/test-id128.c
index 2c8ba70ffb..32cf3f80ca 100644
--- a/src/test/test-id128.c
+++ b/src/test/test-id128.c
@@ -24,6 +24,7 @@
#include "sd-daemon.h"
#include "sd-id128.h"
+#include "alloc-util.h"
#include "macro.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/test/test-json.c b/src/test/test-json.c
index ba4d75c0c8..3995224eea 100644
--- a/src/test/test-json.c
+++ b/src/test/test-json.c
@@ -21,6 +21,7 @@
#include <math.h>
+#include "alloc-util.h"
#include "json.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c
index a060a7ba6f..5a12e959d4 100644
--- a/src/test/test-namespace.c
+++ b/src/test/test-namespace.c
@@ -21,6 +21,7 @@
#include <sys/socket.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "namespace.h"
#include "process-util.h"
diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c
new file mode 100644
index 0000000000..d3ae0599ab
--- /dev/null
+++ b/src/test/test-parse-util.c
@@ -0,0 +1,452 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+ Copyright 2013 Thomas H.P. Andersen
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <locale.h>
+#include <math.h>
+
+#include "log.h"
+#include "parse-util.h"
+
+static void test_parse_boolean(void) {
+ assert_se(parse_boolean("1") == 1);
+ assert_se(parse_boolean("y") == 1);
+ assert_se(parse_boolean("Y") == 1);
+ assert_se(parse_boolean("yes") == 1);
+ assert_se(parse_boolean("YES") == 1);
+ assert_se(parse_boolean("true") == 1);
+ assert_se(parse_boolean("TRUE") == 1);
+ assert_se(parse_boolean("on") == 1);
+ assert_se(parse_boolean("ON") == 1);
+
+ assert_se(parse_boolean("0") == 0);
+ assert_se(parse_boolean("n") == 0);
+ assert_se(parse_boolean("N") == 0);
+ assert_se(parse_boolean("no") == 0);
+ assert_se(parse_boolean("NO") == 0);
+ assert_se(parse_boolean("false") == 0);
+ assert_se(parse_boolean("FALSE") == 0);
+ assert_se(parse_boolean("off") == 0);
+ assert_se(parse_boolean("OFF") == 0);
+
+ assert_se(parse_boolean("garbage") < 0);
+ assert_se(parse_boolean("") < 0);
+ assert_se(parse_boolean("full") < 0);
+}
+
+static void test_parse_pid(void) {
+ int r;
+ pid_t pid;
+
+ r = parse_pid("100", &pid);
+ assert_se(r == 0);
+ assert_se(pid == 100);
+
+ r = parse_pid("0x7FFFFFFF", &pid);
+ assert_se(r == 0);
+ assert_se(pid == 2147483647);
+
+ pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
+ r = parse_pid("0", &pid);
+ assert_se(r == -ERANGE);
+ assert_se(pid == 65);
+
+ pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
+ r = parse_pid("-100", &pid);
+ assert_se(r == -ERANGE);
+ assert_se(pid == 65);
+
+ pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
+ r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid);
+ assert_se(r == -ERANGE);
+ assert_se(pid == 65);
+
+ r = parse_pid("junk", &pid);
+ assert_se(r == -EINVAL);
+}
+
+static void test_parse_mode(void) {
+ mode_t m;
+
+ assert_se(parse_mode("-1", &m) < 0);
+ assert_se(parse_mode("", &m) < 0);
+ assert_se(parse_mode("888", &m) < 0);
+ assert_se(parse_mode("77777", &m) < 0);
+
+ assert_se(parse_mode("544", &m) >= 0 && m == 0544);
+ assert_se(parse_mode("777", &m) >= 0 && m == 0777);
+ assert_se(parse_mode("7777", &m) >= 0 && m == 07777);
+ assert_se(parse_mode("0", &m) >= 0 && m == 0);
+}
+
+static void test_parse_size(void) {
+ uint64_t bytes;
+
+ assert_se(parse_size("111", 1024, &bytes) == 0);
+ assert_se(bytes == 111);
+
+ assert_se(parse_size("111.4", 1024, &bytes) == 0);
+ assert_se(bytes == 111);
+
+ assert_se(parse_size(" 112 B", 1024, &bytes) == 0);
+ assert_se(bytes == 112);
+
+ assert_se(parse_size(" 112.6 B", 1024, &bytes) == 0);
+ assert_se(bytes == 112);
+
+ assert_se(parse_size("3.5 K", 1024, &bytes) == 0);
+ assert_se(bytes == 3*1024 + 512);
+
+ assert_se(parse_size("3. K", 1024, &bytes) == 0);
+ assert_se(bytes == 3*1024);
+
+ assert_se(parse_size("3.0 K", 1024, &bytes) == 0);
+ assert_se(bytes == 3*1024);
+
+ assert_se(parse_size("3. 0 K", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size(" 4 M 11.5K", 1024, &bytes) == 0);
+ assert_se(bytes == 4*1024*1024 + 11 * 1024 + 512);
+
+ assert_se(parse_size("3B3.5G", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size("3.5G3B", 1024, &bytes) == 0);
+ assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 3);
+
+ assert_se(parse_size("3.5G 4B", 1024, &bytes) == 0);
+ assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 4);
+
+ assert_se(parse_size("3B3G4T", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size("4T3G3B", 1024, &bytes) == 0);
+ assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
+
+ assert_se(parse_size(" 4 T 3 G 3 B", 1024, &bytes) == 0);
+ assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
+
+ assert_se(parse_size("12P", 1024, &bytes) == 0);
+ assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
+
+ assert_se(parse_size("12P12P", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size("3E 2P", 1024, &bytes) == 0);
+ assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
+
+ assert_se(parse_size("12X", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size("12.5X", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size("12.5e3", 1024, &bytes) == -EINVAL);
+
+ assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE);
+ assert_se(parse_size("-1", 1024, &bytes) == -ERANGE);
+ assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE);
+
+ assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE);
+
+ assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE);
+}
+
+static void test_parse_range(void) {
+ unsigned lower, upper;
+
+ /* Successful cases */
+ assert_se(parse_range("111", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 111);
+
+ assert_se(parse_range("111-123", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 123);
+
+ assert_se(parse_range("123-111", &lower, &upper) == 0);
+ assert_se(lower == 123);
+ assert_se(upper == 111);
+
+ assert_se(parse_range("123-123", &lower, &upper) == 0);
+ assert_se(lower == 123);
+ assert_se(upper == 123);
+
+ assert_se(parse_range("0", &lower, &upper) == 0);
+ assert_se(lower == 0);
+ assert_se(upper == 0);
+
+ assert_se(parse_range("0-15", &lower, &upper) == 0);
+ assert_se(lower == 0);
+ assert_se(upper == 15);
+
+ assert_se(parse_range("15-0", &lower, &upper) == 0);
+ assert_se(lower == 15);
+ assert_se(upper == 0);
+
+ assert_se(parse_range("128-65535", &lower, &upper) == 0);
+ assert_se(lower == 128);
+ assert_se(upper == 65535);
+
+ assert_se(parse_range("1024-4294967295", &lower, &upper) == 0);
+ assert_se(lower == 1024);
+ assert_se(upper == 4294967295);
+
+ /* Leading whitespace is acceptable */
+ assert_se(parse_range(" 111", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 111);
+
+ assert_se(parse_range(" 111-123", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 123);
+
+ assert_se(parse_range("111- 123", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 123);
+
+ assert_se(parse_range("\t111-\t123", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 123);
+
+ assert_se(parse_range(" \t 111- \t 123", &lower, &upper) == 0);
+ assert_se(lower == 111);
+ assert_se(upper == 123);
+
+ /* Error cases, make sure they fail as expected */
+ lower = upper = 9999;
+ assert_se(parse_range("111garbage", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("garbage111", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("garbage", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111-123garbage", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111garbage-123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ /* Empty string */
+ lower = upper = 9999;
+ assert_se(parse_range("", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ /* 111--123 will pass -123 to safe_atou which returns -ERANGE for negative */
+ assert_se(parse_range("111--123", &lower, &upper) == -ERANGE);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("-111-123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111-123-", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111.4-123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111-123.4", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111,4-123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111-123,4", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ /* Error on trailing dash */
+ assert_se(parse_range("111-", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111-123-", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111--", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111- ", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ /* Whitespace is not a separator */
+ assert_se(parse_range("111 123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111\t123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111 \t 123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ /* Trailing whitespace is invalid (from safe_atou) */
+ assert_se(parse_range("111 ", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111-123 ", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111 -123", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111 -123 ", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111\t-123\t", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ assert_se(parse_range("111 \t -123 \t ", &lower, &upper) == -EINVAL);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+
+ /* Out of the "unsigned" range, this is 1<<64 */
+ assert_se(parse_range("0-18446744073709551616", &lower, &upper) == -ERANGE);
+ assert_se(lower == 9999);
+ assert_se(upper == 9999);
+}
+
+static void test_safe_atolli(void) {
+ int r;
+ long long l;
+
+ r = safe_atolli("12345", &l);
+ assert_se(r == 0);
+ assert_se(l == 12345);
+
+ r = safe_atolli("junk", &l);
+ assert_se(r == -EINVAL);
+}
+
+static void test_safe_atou16(void) {
+ int r;
+ uint16_t l;
+
+ r = safe_atou16("12345", &l);
+ assert_se(r == 0);
+ assert_se(l == 12345);
+
+ r = safe_atou16("123456", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atou16("junk", &l);
+ assert_se(r == -EINVAL);
+}
+
+static void test_safe_atoi16(void) {
+ int r;
+ int16_t l;
+
+ r = safe_atoi16("-12345", &l);
+ assert_se(r == 0);
+ assert_se(l == -12345);
+
+ r = safe_atoi16("36536", &l);
+ assert_se(r == -ERANGE);
+
+ r = safe_atoi16("junk", &l);
+ assert_se(r == -EINVAL);
+}
+
+static void test_safe_atod(void) {
+ int r;
+ double d;
+ char *e;
+
+ r = safe_atod("junk", &d);
+ assert_se(r == -EINVAL);
+
+ r = safe_atod("0.2244", &d);
+ assert_se(r == 0);
+ assert_se(fabs(d - 0.2244) < 0.000001);
+
+ r = safe_atod("0,5", &d);
+ assert_se(r == -EINVAL);
+
+ errno = 0;
+ strtod("0,5", &e);
+ assert_se(*e == ',');
+
+ /* Check if this really is locale independent */
+ if (setlocale(LC_NUMERIC, "de_DE.utf8")) {
+
+ r = safe_atod("0.2244", &d);
+ assert_se(r == 0);
+ assert_se(fabs(d - 0.2244) < 0.000001);
+
+ r = safe_atod("0,5", &d);
+ assert_se(r == -EINVAL);
+
+ errno = 0;
+ assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001);
+ }
+
+ /* And check again, reset */
+ assert_se(setlocale(LC_NUMERIC, "C"));
+
+ r = safe_atod("0.2244", &d);
+ assert_se(r == 0);
+ assert_se(fabs(d - 0.2244) < 0.000001);
+
+ r = safe_atod("0,5", &d);
+ assert_se(r == -EINVAL);
+
+ errno = 0;
+ strtod("0,5", &e);
+ assert_se(*e == ',');
+}
+
+int main(int argc, char *argv[]) {
+ log_parse_environment();
+ log_open();
+
+ test_parse_boolean();
+ test_parse_pid();
+ test_parse_mode();
+ test_parse_size();
+ test_parse_range();
+ test_safe_atolli();
+ test_safe_atou16();
+ test_safe_atoi16();
+ test_safe_atod();
+
+ return 0;
+}
diff --git a/src/test/test-path-lookup.c b/src/test/test-path-lookup.c
index 92ffa65925..65cb894ff7 100644
--- a/src/test/test-path-lookup.c
+++ b/src/test/test-path-lookup.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdlib.h>
#include <sys/stat.h>
#include "log.h"
@@ -30,19 +31,27 @@
static void test_paths(ManagerRunningAs running_as, bool personal) {
char template[] = "/tmp/test-path-lookup.XXXXXXX";
- _cleanup_lookup_paths_free_ LookupPaths lp = {};
- char *exists, *not;
+ _cleanup_lookup_paths_free_ LookupPaths lp_without_env = {};
+ _cleanup_lookup_paths_free_ LookupPaths lp_with_env = {};
+ char *exists, *not, *systemd_unit_path;
assert_se(mkdtemp(template));
exists = strjoina(template, "/exists");
assert_se(mkdir(exists, 0755) == 0);
not = strjoina(template, "/not");
- assert_se(lookup_paths_init(&lp, running_as, personal, NULL, exists, not, not) == 0);
+ assert_se(unsetenv("SYSTEMD_UNIT_PATH") == 0);
+ assert_se(lookup_paths_init(&lp_without_env, running_as, personal, NULL, exists, not, not) == 0);
- assert_se(!strv_isempty(lp.unit_path));
- assert_se(strv_contains(lp.unit_path, exists));
- assert_se(strv_contains(lp.unit_path, not));
+ assert_se(!strv_isempty(lp_without_env.unit_path));
+ assert_se(strv_contains(lp_without_env.unit_path, exists));
+ assert_se(strv_contains(lp_without_env.unit_path, not));
+
+ systemd_unit_path = strjoina(template, "/systemd-unit-path");
+ assert_se(setenv("SYSTEMD_UNIT_PATH", systemd_unit_path, 1) == 0);
+ assert_se(lookup_paths_init(&lp_with_env, running_as, personal, NULL, exists, not, not) == 0);
+ assert_se(strv_length(lp_with_env.unit_path) == 1);
+ assert_se(streq(lp_with_env.unit_path[0], systemd_unit_path));
assert_se(rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 89129c9894..3f0f0264ab 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -23,8 +23,10 @@
#include <sys/mount.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "macro.h"
+#include "mount-util.h"
#include "path-util.h"
#include "rm-rf.h"
#include "string-util.h"
@@ -77,20 +79,6 @@ static void test_path(void) {
assert_se(streq(basename("/aa///file..."), "file..."));
assert_se(streq(basename("file.../"), ""));
-#define test_parent(x, y) { \
- _cleanup_free_ char *z = NULL; \
- int r = path_get_parent(x, &z); \
- printf("expected: %s\n", y ? y : "error"); \
- printf("actual: %s\n", r<0 ? "error" : z); \
- assert_se((y==NULL) ^ (r==0)); \
- assert_se(y==NULL || path_equal(z, y)); \
- }
-
- test_parent("./aa/bb/../file.da.", "./aa/bb/..");
- test_parent("/aa///.file", "/aa///");
- test_parent("/aa///file...", "/aa///");
- test_parent("file.../", NULL);
-
fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY);
assert_se(fd >= 0);
assert_se(fd_is_mount_point(fd, "/", 0) > 0);
diff --git a/src/test/test-path.c b/src/test/test-path.c
index e9e0bfd41d..8302bdd283 100644
--- a/src/test/test-path.c
+++ b/src/test/test-path.c
@@ -20,6 +20,9 @@
#include <stdbool.h>
#include <stdio.h>
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
#include "macro.h"
#include "manager.h"
#include "mkdir.h"
@@ -28,7 +31,6 @@
#include "strv.h"
#include "unit.h"
#include "util.h"
-#include "fd-util.h"
typedef void (*test_function_t)(Manager *m);
@@ -256,7 +258,7 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
- assert_se(set_unit_path(TEST_DIR) >= 0);
+ assert_se(set_unit_path(TEST_DIR "/test-path/") >= 0);
for (test = tests; test && *test; test++) {
int r;
diff --git a/src/test/test-prioq.c b/src/test/test-prioq.c
index 1e2e42cbca..07273ffe79 100644
--- a/src/test/test-prioq.c
+++ b/src/test/test-prioq.c
@@ -21,10 +21,11 @@
#include <stdlib.h>
-#include "util.h"
-#include "set.h"
+#include "alloc-util.h"
#include "prioq.h"
+#include "set.h"
#include "siphash24.h"
+#include "util.h"
#define SET_SIZE 1024*4
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index 16a7148b19..48be5a3a87 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -23,6 +23,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "log.h"
#include "macro.h"
#include "process-util.h"
@@ -54,7 +55,7 @@ static void test_get_process_comm(void) {
assert_se(get_process_cmdline(1, 8, false, &d) >= 0);
log_info("pid1 cmdline truncated: '%s'", d);
- assert_se(get_parent_of_pid(1, &e) >= 0);
+ assert_se(get_process_ppid(1, &e) >= 0);
log_info("pid1 ppid: "PID_FMT, e);
assert_se(e == 0);
diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c
index 4a2d952c86..b9699b2028 100644
--- a/src/test/test-socket-util.c
+++ b/src/test/test-socket-util.c
@@ -17,6 +17,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "async.h"
#include "fd-util.h"
#include "in-addr-util.h"
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index c676893719..c27f15283e 100644
--- a/src/test/test-strv.c
+++ b/src/test/test-strv.c
@@ -22,6 +22,7 @@
#include <string.h>
+#include "alloc-util.h"
#include "specifier.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
index 0e5ab1645f..ed4abdbf12 100644
--- a/src/test/test-tables.c
+++ b/src/test/test-tables.c
@@ -17,7 +17,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "architecture.h"
#include "automount.h"
+#include "bus-xml-policy.h"
+#include "busname.h"
#include "cgroup.h"
#include "compress.h"
#include "condition.h"
@@ -25,7 +28,10 @@
#include "execute.h"
#include "install.h"
#include "job.h"
+#include "journald-server.h"
#include "kill.h"
+#include "link-config.h"
+#include "locale-util.h"
#include "log.h"
#include "logs-show.h"
#include "mount.h"
@@ -42,12 +48,7 @@
#include "unit-name.h"
#include "unit.h"
#include "util.h"
-#include "architecture.h"
-#include "link-config.h"
-#include "bus-xml-policy.h"
-#include "busname.h"
-#include "journald-server.h"
-#include "locale-util.h"
+#include "rlimit-util.h"
#include "test-tables.h"
diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c
index a41de59719..e940b5a204 100644
--- a/src/test/test-terminal-util.c
+++ b/src/test/test-terminal-util.c
@@ -21,11 +21,12 @@
#include <stdio.h>
#include <stdbool.h>
-#include "terminal-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "log.h"
#include "macro.h"
+#include "terminal-util.h"
#include "util.h"
-#include "log.h"
-#include "fd-util.h"
static void test_default_term_for_tty(void) {
puts(default_term_for_tty("/dev/tty23"));
diff --git a/src/test/test-tmpfiles.c b/src/test/test-tmpfiles.c
index 6aa9cc8473..a8bd722e44 100644
--- a/src/test/test-tmpfiles.c
+++ b/src/test/test-tmpfiles.c
@@ -24,7 +24,9 @@
#include <stdlib.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
+#include "fileio.h"
#include "formats-util.h"
#include "string-util.h"
#include "util.h"
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
index 3b9f71e3a2..219d659b41 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -26,6 +26,7 @@
#include <sys/signalfd.h>
#include <unistd.h>
+#include "fs-util.h"
#include "missing.h"
#include "selinux-util.h"
#include "signal-util.h"
diff --git a/src/test/test-uid-range.c b/src/test/test-uid-range.c
index bc5baa2fcb..4dcf10e26d 100644
--- a/src/test/test-uid-range.c
+++ b/src/test/test-uid-range.c
@@ -21,8 +21,10 @@
#include <stddef.h>
-#include "util.h"
+#include "alloc-util.h"
#include "uid-range.h"
+#include "user-util.h"
+#include "util.h"
int main(int argc, char *argv[]) {
_cleanup_free_ UidRange *p = NULL;
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index 226453d06e..f9107e0d0d 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -24,8 +24,10 @@
#include <stddef.h>
#include <stdio.h>
#include <string.h>
+#include <sys/capability.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "hashmap.h"
@@ -628,6 +630,57 @@ static void test_install_printf(void) {
expect(i4, "%U", "0");
}
+static uint64_t make_cap(int cap) {
+ return ((uint64_t) 1ULL << (uint64_t) cap);
+}
+
+static void test_config_parse_bounding_set(void) {
+ /* int config_parse_bounding_set(
+ 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) */
+ int r;
+ uint64_t capability_bounding_set_drop = 0;
+
+ r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "CAP_NET_RAW",
+ &capability_bounding_set_drop, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set_drop == ~make_cap(CAP_NET_RAW));
+
+ r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
+ &capability_bounding_set_drop, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
+
+ r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "",
+ &capability_bounding_set_drop, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set_drop == ~((uint64_t) 0ULL));
+
+ r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "~",
+ &capability_bounding_set_drop, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set_drop == (uint64_t) 0ULL);
+
+ capability_bounding_set_drop = 0;
+ r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
+ &capability_bounding_set_drop, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
+}
+
int main(int argc, char *argv[]) {
int r;
@@ -636,6 +689,7 @@ int main(int argc, char *argv[]) {
r = test_unit_file_get_set();
test_config_parse_exec();
+ test_config_parse_bounding_set();
test_load_env_file_1();
test_load_env_file_2();
test_load_env_file_3();
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index 5aff771af5..9db7853dd4 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <string.h>
+#include "alloc-util.h"
#include "hostname-util.h"
#include "macro.h"
#include "manager.h"
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
index dfd2031998..09d37087e5 100644
--- a/src/test/test-user-util.c
+++ b/src/test/test-user-util.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "macro.h"
#include "string-util.h"
#include "user-util.h"
diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c
index a8e15b7cf1..0af8349732 100644
--- a/src/test/test-utf8.c
+++ b/src/test/test-utf8.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "utf8.h"
#include "util.h"
#include "string-util.h"
diff --git a/src/test/test-util.c b/src/test/test-util.c
index c1f8a866af..647df4f5c3 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -22,8 +22,6 @@
#include <errno.h>
#include <fcntl.h>
-#include <locale.h>
-#include <math.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
@@ -31,22 +29,33 @@
#include <sys/xattr.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "conf-parser.h"
#include "cpu-set-util.h"
#include "def.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
+#include "fstab-util.h"
+#include "glob-util.h"
+#include "hexdecoct.h"
#include "io-util.h"
#include "mkdir.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "proc-cmdline.h"
#include "process-util.h"
#include "rm-rf.h"
#include "signal-util.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
+#include "user-util.h"
#include "util.h"
#include "virt.h"
-#include "user-util.h"
+#include "web-util.h"
+#include "xattr-util.h"
static void test_streq_ptr(void) {
assert_se(streq_ptr(NULL, NULL));
@@ -226,63 +235,6 @@ static void test_close_many(void) {
unlink(name2);
}
-static void test_parse_boolean(void) {
- assert_se(parse_boolean("1") == 1);
- assert_se(parse_boolean("y") == 1);
- assert_se(parse_boolean("Y") == 1);
- assert_se(parse_boolean("yes") == 1);
- assert_se(parse_boolean("YES") == 1);
- assert_se(parse_boolean("true") == 1);
- assert_se(parse_boolean("TRUE") == 1);
- assert_se(parse_boolean("on") == 1);
- assert_se(parse_boolean("ON") == 1);
-
- assert_se(parse_boolean("0") == 0);
- assert_se(parse_boolean("n") == 0);
- assert_se(parse_boolean("N") == 0);
- assert_se(parse_boolean("no") == 0);
- assert_se(parse_boolean("NO") == 0);
- assert_se(parse_boolean("false") == 0);
- assert_se(parse_boolean("FALSE") == 0);
- assert_se(parse_boolean("off") == 0);
- assert_se(parse_boolean("OFF") == 0);
-
- assert_se(parse_boolean("garbage") < 0);
- assert_se(parse_boolean("") < 0);
- assert_se(parse_boolean("full") < 0);
-}
-
-static void test_parse_pid(void) {
- int r;
- pid_t pid;
-
- r = parse_pid("100", &pid);
- assert_se(r == 0);
- assert_se(pid == 100);
-
- r = parse_pid("0x7FFFFFFF", &pid);
- assert_se(r == 0);
- assert_se(pid == 2147483647);
-
- pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
- r = parse_pid("0", &pid);
- assert_se(r == -ERANGE);
- assert_se(pid == 65);
-
- pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
- r = parse_pid("-100", &pid);
- assert_se(r == -ERANGE);
- assert_se(pid == 65);
-
- pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
- r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid);
- assert_se(r == -ERANGE);
- assert_se(pid == 65);
-
- r = parse_pid("junk", &pid);
- assert_se(r == -EINVAL);
-}
-
static void test_parse_uid(void) {
int r;
uid_t uid;
@@ -298,96 +250,6 @@ static void test_parse_uid(void) {
assert_se(r == -EINVAL);
}
-static void test_safe_atou16(void) {
- int r;
- uint16_t l;
-
- r = safe_atou16("12345", &l);
- assert_se(r == 0);
- assert_se(l == 12345);
-
- r = safe_atou16("123456", &l);
- assert_se(r == -ERANGE);
-
- r = safe_atou16("junk", &l);
- assert_se(r == -EINVAL);
-}
-
-static void test_safe_atoi16(void) {
- int r;
- int16_t l;
-
- r = safe_atoi16("-12345", &l);
- assert_se(r == 0);
- assert_se(l == -12345);
-
- r = safe_atoi16("36536", &l);
- assert_se(r == -ERANGE);
-
- r = safe_atoi16("junk", &l);
- assert_se(r == -EINVAL);
-}
-
-static void test_safe_atolli(void) {
- int r;
- long long l;
-
- r = safe_atolli("12345", &l);
- assert_se(r == 0);
- assert_se(l == 12345);
-
- r = safe_atolli("junk", &l);
- assert_se(r == -EINVAL);
-}
-
-static void test_safe_atod(void) {
- int r;
- double d;
- char *e;
-
- r = safe_atod("junk", &d);
- assert_se(r == -EINVAL);
-
- r = safe_atod("0.2244", &d);
- assert_se(r == 0);
- assert_se(fabs(d - 0.2244) < 0.000001);
-
- r = safe_atod("0,5", &d);
- assert_se(r == -EINVAL);
-
- errno = 0;
- strtod("0,5", &e);
- assert_se(*e == ',');
-
- /* Check if this really is locale independent */
- if (setlocale(LC_NUMERIC, "de_DE.utf8")) {
-
- r = safe_atod("0.2244", &d);
- assert_se(r == 0);
- assert_se(fabs(d - 0.2244) < 0.000001);
-
- r = safe_atod("0,5", &d);
- assert_se(r == -EINVAL);
-
- errno = 0;
- assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001);
- }
-
- /* And check again, reset */
- assert_se(setlocale(LC_NUMERIC, "C"));
-
- r = safe_atod("0.2244", &d);
- assert_se(r == 0);
- assert_se(fabs(d - 0.2244) < 0.000001);
-
- r = safe_atod("0,5", &d);
- assert_se(r == -EINVAL);
-
- errno = 0;
- strtod("0,5", &e);
- assert_se(*e == ',');
-}
-
static void test_strappend(void) {
_cleanup_free_ char *t1, *t2, *t3, *t4;
@@ -900,74 +762,6 @@ static void test_protect_errno(void) {
assert_se(errno == 12);
}
-static void test_parse_size(void) {
- uint64_t bytes;
-
- assert_se(parse_size("111", 1024, &bytes) == 0);
- assert_se(bytes == 111);
-
- assert_se(parse_size("111.4", 1024, &bytes) == 0);
- assert_se(bytes == 111);
-
- assert_se(parse_size(" 112 B", 1024, &bytes) == 0);
- assert_se(bytes == 112);
-
- assert_se(parse_size(" 112.6 B", 1024, &bytes) == 0);
- assert_se(bytes == 112);
-
- assert_se(parse_size("3.5 K", 1024, &bytes) == 0);
- assert_se(bytes == 3*1024 + 512);
-
- assert_se(parse_size("3. K", 1024, &bytes) == 0);
- assert_se(bytes == 3*1024);
-
- assert_se(parse_size("3.0 K", 1024, &bytes) == 0);
- assert_se(bytes == 3*1024);
-
- assert_se(parse_size("3. 0 K", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size(" 4 M 11.5K", 1024, &bytes) == 0);
- assert_se(bytes == 4*1024*1024 + 11 * 1024 + 512);
-
- assert_se(parse_size("3B3.5G", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size("3.5G3B", 1024, &bytes) == 0);
- assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 3);
-
- assert_se(parse_size("3.5G 4B", 1024, &bytes) == 0);
- assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 4);
-
- assert_se(parse_size("3B3G4T", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size("4T3G3B", 1024, &bytes) == 0);
- assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
-
- assert_se(parse_size(" 4 T 3 G 3 B", 1024, &bytes) == 0);
- assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
-
- assert_se(parse_size("12P", 1024, &bytes) == 0);
- assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
-
- assert_se(parse_size("12P12P", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size("3E 2P", 1024, &bytes) == 0);
- assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
-
- assert_se(parse_size("12X", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size("12.5X", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size("12.5e3", 1024, &bytes) == -EINVAL);
-
- assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE);
- assert_se(parse_size("-1", 1024, &bytes) == -ERANGE);
- assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE);
-
- assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE);
-
- assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE);
-}
-
static void test_parse_cpu_set(void) {
cpu_set_t *c = NULL;
int ncpus;
@@ -1001,19 +795,76 @@ static void test_parse_cpu_set(void) {
/* Use commas as separators */
ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Commas with spaces (and trailing comma, space) */
+ ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 8; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
/* Ranges */
ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Ranges with trailing comma, space */
+ ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Negative range (returns empty cpu_set) */
+ ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0);
+ c = mfree(c);
+
+ /* Overlapping ranges */
+ ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12);
+ for (cpu = 0; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Mix ranges and individual CPUs */
+ ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10);
+ assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 4; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
/* Garbage */
ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity");
assert_se(ncpus < 0);
assert_se(!c);
+ /* Range with garbage */
+ ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+
/* Empty string */
c = NULL;
ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity");
@@ -1559,513 +1410,6 @@ static void test_execute_directory(void) {
(void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
}
-static void test_extract_first_word(void) {
- const char *p, *original;
- char *t;
-
- p = original = "foobar waldo";
- assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
- assert_se(streq(t, "foobar"));
- free(t);
- assert_se(p == original + 7);
-
- assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
- assert_se(streq(t, "waldo"));
- free(t);
- assert_se(isempty(p));
-
- assert_se(extract_first_word(&p, &t, NULL, 0) == 0);
- assert_se(!t);
- assert_se(isempty(p));
-
- p = original = "\"foobar\" \'waldo\'";
- assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
- assert_se(streq(t, "\"foobar\""));
- free(t);
- assert_se(p == original + 9);
-
- assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
- assert_se(streq(t, "\'waldo\'"));
- free(t);
- assert_se(isempty(p));
-
- assert_se(extract_first_word(&p, &t, NULL, 0) == 0);
- assert_se(!t);
- assert_se(isempty(p));
-
- p = original = "\"foobar\" \'waldo\'";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
- assert_se(streq(t, "foobar"));
- free(t);
- assert_se(p == original + 9);
-
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
- assert_se(streq(t, "waldo"));
- free(t);
- assert_se(isempty(p));
-
- assert_se(extract_first_word(&p, &t, NULL, 0) == 0);
- assert_se(!t);
- assert_se(isempty(p));
-
- p = original = "\"";
- assert_se(extract_first_word(&p, &t, NULL, 0) == 1);
- assert_se(streq(t, "\""));
- free(t);
- assert_se(isempty(p));
-
- p = original = "\"";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
- assert_se(p == original + 1);
-
- p = original = "\'";
- assert_se(extract_first_word(&p, &t, NULL, 0) == 1);
- assert_se(streq(t, "\'"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "\'";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
- assert_se(p == original + 1);
-
- p = original = "\'fooo";
- assert_se(extract_first_word(&p, &t, NULL, 0) == 1);
- assert_se(streq(t, "\'fooo"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "\'fooo";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "\'fooo";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
- assert_se(streq(t, "fooo"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "\"fooo";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
- assert_se(streq(t, "fooo"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "yay\'foo\'bar";
- assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
- assert_se(streq(t, "yay\'foo\'bar"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "yay\'foo\'bar";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
- assert_se(streq(t, "yayfoobar"));
- free(t);
- assert_se(isempty(p));
-
- p = original = " foobar ";
- assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
- assert_se(streq(t, "foobar"));
- free(t);
- assert_se(isempty(p));
-
- p = original = " foo\\ba\\x6ar ";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0);
- assert_se(streq(t, "foo\ba\x6ar"));
- free(t);
- assert_se(isempty(p));
-
- p = original = " foo\\ba\\x6ar ";
- assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
- assert_se(streq(t, "foobax6ar"));
- free(t);
- assert_se(isempty(p));
-
- p = original = " f\\u00f6o \"pi\\U0001F4A9le\" ";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0);
- assert_se(streq(t, "föo"));
- free(t);
- assert_se(p == original + 13);
-
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE) > 0);
- assert_se(streq(t, "pi\360\237\222\251le"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "fooo\\";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0);
- assert_se(streq(t, "fooo"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "fooo\\";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0);
- assert_se(streq(t, "fooo\\"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "fooo\\";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
- assert_se(streq(t, "fooo\\"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "fooo\\";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
- assert_se(streq(t, "fooo\\"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "\"foo\\";
- assert_se(extract_first_word(&p, &t, NULL, 0) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
- assert_se(streq(t, "foo"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "foo::bar";
- assert_se(extract_first_word(&p, &t, ":", 0) == 1);
- assert_se(streq(t, "foo"));
- free(t);
- assert_se(p == original + 5);
-
- assert_se(extract_first_word(&p, &t, ":", 0) == 1);
- assert_se(streq(t, "bar"));
- free(t);
- assert_se(isempty(p));
-
- assert_se(extract_first_word(&p, &t, ":", 0) == 0);
- assert_se(!t);
- assert_se(isempty(p));
-
- p = original = "foo\\:bar::waldo";
- assert_se(extract_first_word(&p, &t, ":", 0) == 1);
- assert_se(streq(t, "foo:bar"));
- free(t);
- assert_se(p == original + 10);
-
- assert_se(extract_first_word(&p, &t, ":", 0) == 1);
- assert_se(streq(t, "waldo"));
- free(t);
- assert_se(isempty(p));
-
- assert_se(extract_first_word(&p, &t, ":", 0) == 0);
- assert_se(!t);
- assert_se(isempty(p));
-
- p = original = "\"foo\\";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
- assert_se(streq(t, "foo\\"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "\"foo\\";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
- assert_se(streq(t, "foo\\"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "fooo\\ bar quux";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0);
- assert_se(streq(t, "fooo bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "fooo\\ bar quux";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0);
- assert_se(streq(t, "fooo bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "fooo\\ bar quux";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
- assert_se(streq(t, "fooo bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "fooo\\ bar quux";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "fooo\\ bar quux";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
- assert_se(streq(t, "fooo\\ bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "\\w+@\\K[\\d.]+";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL);
- assert_se(p == original + 1);
-
- p = original = "\\w+@\\K[\\d.]+";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
- assert_se(streq(t, "\\w+@\\K[\\d.]+"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "\\w+\\b";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
- assert_se(streq(t, "\\w+\b"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "-N ''";
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
- assert_se(streq(t, "-N"));
- free(t);
- assert_se(p == original + 3);
-
- assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
- assert_se(streq(t, ""));
- free(t);
- assert_se(isempty(p));
-
- p = original = ":foo\\:bar::waldo:";
- assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
- assert_se(t);
- assert_se(streq(t, ""));
- free(t);
- assert_se(p == original + 1);
-
- assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
- assert_se(streq(t, "foo:bar"));
- free(t);
- assert_se(p == original + 10);
-
- assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
- assert_se(t);
- assert_se(streq(t, ""));
- free(t);
- assert_se(p == original + 11);
-
- assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
- assert_se(streq(t, "waldo"));
- free(t);
- assert_se(p == original + 17);
-
- assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
- assert_se(streq(t, ""));
- free(t);
- assert_se(p == NULL);
-
- assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 0);
- assert_se(!t);
- assert_se(!p);
-}
-
-static void test_extract_first_word_and_warn(void) {
- const char *p, *original;
- char *t;
-
- p = original = "foobar waldo";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "foobar"));
- free(t);
- assert_se(p == original + 7);
-
- assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "waldo"));
- free(t);
- assert_se(isempty(p));
-
- assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0);
- assert_se(!t);
- assert_se(isempty(p));
-
- p = original = "\"foobar\" \'waldo\'";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "foobar"));
- free(t);
- assert_se(p == original + 9);
-
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "waldo"));
- free(t);
- assert_se(isempty(p));
-
- assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0);
- assert_se(!t);
- assert_se(isempty(p));
-
- p = original = "\"";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
- assert_se(p == original + 1);
-
- p = original = "\'";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
- assert_se(p == original + 1);
-
- p = original = "\'fooo";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "\'fooo";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo"));
- free(t);
- assert_se(isempty(p));
-
- p = original = " foo\\ba\\x6ar ";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "foo\ba\x6ar"));
- free(t);
- assert_se(isempty(p));
-
- p = original = " foo\\ba\\x6ar ";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "foobax6ar"));
- free(t);
- assert_se(isempty(p));
-
- p = original = " f\\u00f6o \"pi\\U0001F4A9le\" ";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "föo"));
- free(t);
- assert_se(p == original + 13);
-
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "pi\360\237\222\251le"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "fooo\\";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "fooo\\";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo\\"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "fooo\\";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo\\"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "\"foo\\";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "foo"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "\"foo\\";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) == -EINVAL);
- assert_se(p == original + 5);
-
- p = original = "\"foo\\";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "foo"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "fooo\\ bar quux";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "fooo\\ bar quux";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "fooo\\ bar quux";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "fooo\\ bar"));
- free(t);
- assert_se(p == original + 10);
-
- p = original = "\\w+@\\K[\\d.]+";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "\\w+@\\K[\\d.]+"));
- free(t);
- assert_se(isempty(p));
-
- p = original = "\\w+\\b";
- assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
- assert_se(streq(t, "\\w+\b"));
- free(t);
- assert_se(isempty(p));
-}
-
-static void test_extract_many_words(void) {
- const char *p, *original;
- char *a, *b, *c;
-
- p = original = "foobar waldi piep";
- assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 3);
- assert_se(isempty(p));
- assert_se(streq_ptr(a, "foobar"));
- assert_se(streq_ptr(b, "waldi"));
- assert_se(streq_ptr(c, "piep"));
- free(a);
- free(b);
- free(c);
-
- p = original = "'foobar' wa\"ld\"i ";
- assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 2);
- assert_se(isempty(p));
- assert_se(streq_ptr(a, "'foobar'"));
- assert_se(streq_ptr(b, "wa\"ld\"i"));
- assert_se(streq_ptr(c, NULL));
- free(a);
- free(b);
-
- p = original = "'foobar' wa\"ld\"i ";
- assert_se(extract_many_words(&p, NULL, EXTRACT_QUOTES, &a, &b, &c, NULL) == 2);
- assert_se(isempty(p));
- assert_se(streq_ptr(a, "foobar"));
- assert_se(streq_ptr(b, "waldi"));
- assert_se(streq_ptr(c, NULL));
- free(a);
- free(b);
-
- p = original = "";
- assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0);
- assert_se(isempty(p));
- assert_se(streq_ptr(a, NULL));
- assert_se(streq_ptr(b, NULL));
- assert_se(streq_ptr(c, NULL));
-
- p = original = " ";
- assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0);
- assert_se(isempty(p));
- assert_se(streq_ptr(a, NULL));
- assert_se(streq_ptr(b, NULL));
- assert_se(streq_ptr(c, NULL));
-
- p = original = "foobar";
- assert_se(extract_many_words(&p, NULL, 0, NULL) == 0);
- assert_se(p == original);
-
- p = original = "foobar waldi";
- assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1);
- assert_se(p == original+7);
- assert_se(streq_ptr(a, "foobar"));
- free(a);
-
- p = original = " foobar ";
- assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1);
- assert_se(isempty(p));
- assert_se(streq_ptr(a, "foobar"));
- free(a);
-}
-
static int parse_item(const char *key, const char *value) {
assert_se(key);
@@ -2214,20 +1558,6 @@ static void test_shell_maybe_quote(void) {
test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
}
-static void test_parse_mode(void) {
- mode_t m;
-
- assert_se(parse_mode("-1", &m) < 0);
- assert_se(parse_mode("", &m) < 0);
- assert_se(parse_mode("888", &m) < 0);
- assert_se(parse_mode("77777", &m) < 0);
-
- assert_se(parse_mode("544", &m) >= 0 && m == 0544);
- assert_se(parse_mode("777", &m) >= 0 && m == 0777);
- assert_se(parse_mode("7777", &m) >= 0 && m == 07777);
- assert_se(parse_mode("0", &m) >= 0 && m == 0);
-}
-
static void test_tempfn(void) {
char *ret = NULL, *p;
@@ -2320,13 +1650,7 @@ int main(int argc, char *argv[]) {
test_div_round_up();
test_first_word();
test_close_many();
- test_parse_boolean();
- test_parse_pid();
test_parse_uid();
- test_safe_atou16();
- test_safe_atoi16();
- test_safe_atolli();
- test_safe_atod();
test_strappend();
test_strstrip();
test_delete_chars();
@@ -2353,7 +1677,6 @@ int main(int argc, char *argv[]) {
test_memdup_multiply();
test_u64log2();
test_protect_errno();
- test_parse_size();
test_parse_cpu_set();
test_config_parse_iec_uint64();
test_strextend();
@@ -2385,9 +1708,6 @@ int main(int argc, char *argv[]) {
test_search_and_fopen_nulstr();
test_glob_exists();
test_execute_directory();
- test_extract_first_word();
- test_extract_first_word_and_warn();
- test_extract_many_words();
test_parse_proc_cmdline();
test_raw_clone();
test_same_fd();
@@ -2395,7 +1715,6 @@ int main(int argc, char *argv[]) {
test_sparse_write();
test_shell_escape();
test_shell_maybe_quote();
- test_parse_mode();
test_tempfn();
test_strcmp_ptr();
test_fgetxattrat_fake();
diff --git a/src/test/test-xml.c b/src/test/test-xml.c
index 93b0e7c3fb..548d75a3c3 100644
--- a/src/test/test-xml.c
+++ b/src/test/test-xml.c
@@ -21,6 +21,7 @@
#include <stdarg.h>
+#include "alloc-util.h"
#include "string-util.h"
#include "util.h"
#include "xml.h"
diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c
index 68fbe3f5b8..564d72773a 100644
--- a/src/timedate/timedatectl.c
+++ b/src/timedate/timedatectl.c
@@ -30,6 +30,7 @@
#include "bus-error.h"
#include "bus-util.h"
#include "pager.h"
+#include "parse-util.h"
#include "spawn-polkit-agent.h"
#include "strv.h"
#include "terminal-util.h"
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 6de9e246f6..968ef8a788 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -23,21 +23,24 @@
#include <string.h>
#include <unistd.h>
-#include "sd-messages.h"
-#include "sd-event.h"
#include "sd-bus.h"
+#include "sd-event.h"
+#include "sd-messages.h"
-#include "util.h"
-#include "strv.h"
-#include "def.h"
-#include "clock-util.h"
-#include "path-util.h"
-#include "fileio-label.h"
-#include "bus-util.h"
-#include "bus-error.h"
+#include "alloc-util.h"
#include "bus-common-errors.h"
+#include "bus-error.h"
+#include "bus-util.h"
+#include "clock-util.h"
+#include "def.h"
#include "event-util.h"
+#include "fileio-label.h"
+#include "fs-util.h"
+#include "path-util.h"
#include "selinux-util.h"
+#include "strv.h"
+#include "user-util.h"
+#include "util.h"
#define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n"
#define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n"
diff --git a/src/timesync/timesyncd-conf.c b/src/timesync/timesyncd-conf.c
index 28e0636604..be651fc636 100644
--- a/src/timesync/timesyncd-conf.c
+++ b/src/timesync/timesyncd-conf.c
@@ -19,14 +19,14 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "string-util.h"
#include "timesyncd-manager.h"
#include "timesyncd-server.h"
#include "timesyncd-conf.h"
+#include "extract-word.h"
int manager_parse_server_string(Manager *m, ServerType type, const char *string) {
- const char *word, *state;
- size_t length;
ServerName *first;
int r;
@@ -35,17 +35,20 @@ int manager_parse_server_string(Manager *m, ServerType type, const char *string)
first = type == SERVER_FALLBACK ? m->fallback_servers : m->system_servers;
- FOREACH_WORD_QUOTED(word, length, string, state) {
- char buffer[length+1];
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
bool found = false;
ServerName *n;
- memcpy(buffer, word, length);
- buffer[length] = 0;
+ r = extract_first_word(&string, &word, NULL, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse timesyncd server syntax \"%s\": %m", string);
+ if (r == 0)
+ break;
/* Filter out duplicates */
LIST_FOREACH(names, n, first)
- if (streq_ptr(n->string, buffer)) {
+ if (streq_ptr(n->string, word)) {
found = true;
break;
}
@@ -53,7 +56,7 @@ int manager_parse_server_string(Manager *m, ServerType type, const char *string)
if (found)
continue;
- r = server_name_new(m, NULL, type, buffer);
+ r = server_name_new(m, NULL, type, word);
if (r < 0)
return r;
}
diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c
index d44cf0a80b..b4995c3064 100644
--- a/src/timesync/timesyncd-manager.c
+++ b/src/timesync/timesyncd-manager.c
@@ -33,7 +33,9 @@
#include "sd-daemon.h"
+#include "alloc-util.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "list.h"
#include "log.h"
#include "missing.h"
diff --git a/src/timesync/timesyncd-server.c b/src/timesync/timesyncd-server.c
index ec3fe1fc4e..f98e6b4cf0 100644
--- a/src/timesync/timesyncd-server.c
+++ b/src/timesync/timesyncd-server.c
@@ -19,6 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "timesyncd-server.h"
int server_address_new(
diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c
index 7a0ab18ca0..7f70eaaea0 100644
--- a/src/timesync/timesyncd.c
+++ b/src/timesync/timesyncd.c
@@ -22,9 +22,10 @@
#include "sd-daemon.h"
#include "sd-event.h"
-#include "capability.h"
+#include "capability-util.h"
#include "clock-util.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "network-util.h"
#include "signal-util.h"
#include "timesyncd-conf.h"
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 05c4661a2c..45335425ce 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -39,26 +39,37 @@
#include <unistd.h>
#include "acl-util.h"
+#include "alloc-util.h"
#include "btrfs-util.h"
-#include "capability.h"
+#include "capability-util.h"
+#include "chattr-util.h"
#include "conf-files.h"
#include "copy.h"
#include "escape.h"
#include "fd-util.h"
+#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
+#include "glob-util.h"
#include "io-util.h"
#include "label.h"
#include "log.h"
#include "macro.h"
#include "missing.h"
#include "mkdir.h"
+#include "mount-util.h"
+#include "parse-util.h"
#include "path-util.h"
#include "rm-rf.h"
#include "selinux-util.h"
#include "set.h"
#include "specifier.h"
+#include "stat-util.h"
+#include "stdio-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
+#include "umask-util.h"
#include "user-util.h"
#include "util.h"
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
index 33419f6962..d2938f0872 100644
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -32,9 +32,11 @@
#include <sys/un.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "ask-password-api.h"
#include "conf-parser.h"
#include "def.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "io-util.h"
#include "mkdir.h"
diff --git a/src/udev/collect/collect.c b/src/udev/collect/collect.c
index b234792e23..b6c95cd452 100644
--- a/src/udev/collect/collect.c
+++ b/src/udev/collect/collect.c
@@ -24,6 +24,7 @@
#include <stddef.h>
#include <stdio.h>
+#include "alloc-util.h"
#include "libudev-private.h"
#include "macro.h"
#include "string-util.h"
diff --git a/src/udev/net/ethtool-util.c b/src/udev/net/ethtool-util.c
index a4b05d1bec..0647008d90 100644
--- a/src/udev/net/ethtool-util.c
+++ b/src/udev/net/ethtool-util.c
@@ -19,17 +19,17 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/ioctl.h>
#include <net/if.h>
+#include <sys/ioctl.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>
+#include "conf-parser.h"
#include "ethtool-util.h"
-
+#include "log.h"
+#include "string-table.h"
#include "strxcpyx.h"
#include "util.h"
-#include "log.h"
-#include "conf-parser.h"
static const char* const duplex_table[_DUP_MAX] = {
[DUP_FULL] = "full",
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index e9577930e3..776674e994 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -24,6 +24,7 @@
#include "sd-netlink.h"
+#include "alloc-util.h"
#include "conf-files.h"
#include "conf-parser.h"
#include "ethtool-util.h"
@@ -34,8 +35,12 @@
#include "missing.h"
#include "netlink-util.h"
#include "network-internal.h"
+#include "parse-util.h"
#include "path-util.h"
+#include "proc-cmdline.h"
#include "random-util.h"
+#include "stat-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
index 0976525eb3..d0e47ec6d8 100644
--- a/src/udev/udev-builtin-blkid.c
+++ b/src/udev/udev-builtin-blkid.c
@@ -29,6 +29,7 @@
#include "sd-id128.h"
+#include "alloc-util.h"
#include "efivars.h"
#include "fd-util.h"
#include "gpt.h"
diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c
index 97a5a9c77f..f4a065a97d 100644
--- a/src/udev/udev-builtin-hwdb.c
+++ b/src/udev/udev-builtin-hwdb.c
@@ -24,6 +24,7 @@
#include "sd-hwdb.h"
+#include "alloc-util.h"
#include "hwdb-util.h"
#include "string-util.h"
#include "udev-util.h"
diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
index 5e97bdd614..aa10beafb0 100644
--- a/src/udev/udev-builtin-keyboard.c
+++ b/src/udev/udev-builtin-keyboard.c
@@ -24,6 +24,8 @@
#include <linux/input.h>
#include "fd-util.h"
+#include "parse-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "udev.h"
diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c
index d4589470fb..f72894b5c5 100644
--- a/src/udev/udev-builtin-net_setup_link.c
+++ b/src/udev/udev-builtin-net_setup_link.c
@@ -19,9 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "link-config.h"
-#include "udev.h"
#include "log.h"
+#include "udev.h"
static link_config_ctx *ctx = NULL;
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index 2c40988c7a..1e190140b2 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -30,6 +30,7 @@
#include <string.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "string-util.h"
#include "udev.h"
diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c
index cb531bd168..587649eff0 100644
--- a/src/udev/udev-builtin-usb_id.c
+++ b/src/udev/udev-builtin-usb_id.c
@@ -29,6 +29,7 @@
#include <string.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "string-util.h"
#include "udev.h"
diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c
index 937fc4ecd8..1e05be51a5 100644
--- a/src/udev/udev-ctrl.c
+++ b/src/udev/udev-ctrl.c
@@ -18,6 +18,7 @@
#include <sys/socket.h>
#include <sys/un.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "formats-util.h"
#include "socket-util.h"
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index bf122f85c7..6b4bd31281 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -30,6 +30,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "event-util.h"
#include "fd-util.h"
#include "formats-util.h"
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 4ed6416ecd..afdeb0a21b 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -26,6 +26,7 @@
#include <unistd.h>
#include "formats-util.h"
+#include "fs-util.h"
#include "selinux-util.h"
#include "smack-util.h"
#include "string-util.h"
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 311d515645..c06ace09cf 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -29,10 +29,13 @@
#include <time.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "conf-files.h"
#include "escape.h"
#include "fd-util.h"
+#include "glob-util.h"
#include "path-util.h"
+#include "stat-util.h"
#include "strbuf.h"
#include "string-util.h"
#include "strv.h"
diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c
index f9509ad640..031a099d77 100644
--- a/src/udev/udevadm-hwdb.c
+++ b/src/udev/udevadm-hwdb.c
@@ -22,7 +22,10 @@
#include <stdlib.h>
#include <string.h>
+#include "alloc-util.h"
#include "conf-files.h"
+#include "fileio.h"
+#include "fs-util.h"
#include "hwdb-internal.h"
#include "hwdb-util.h"
#include "strbuf.h"
diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c
index 3d6ca7a985..c25071b0fe 100644
--- a/src/udev/udevadm-settle.c
+++ b/src/udev/udevadm-settle.c
@@ -26,6 +26,7 @@
#include <getopt.h>
#include <poll.h>
+#include "parse-util.h"
#include "udev.h"
#include "util.h"
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index df5fd88bff..2c152129cc 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -43,6 +43,7 @@
#include "sd-daemon.h"
#include "sd-event.h"
+#include "alloc-util.h"
#include "cgroup-util.h"
#include "cpu-set-util.h"
#include "dev-setup.h"
@@ -50,16 +51,21 @@
#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "io-util.h"
#include "netlink-util.h"
+#include "parse-util.h"
+#include "proc-cmdline.h"
#include "process-util.h"
#include "selinux-util.h"
#include "signal-util.h"
+#include "socket-util.h"
#include "string-util.h"
#include "terminal-util.h"
#include "udev-util.h"
#include "udev.h"
+#include "user-util.h"
static bool arg_debug = false;
static int arg_daemonize = false;
diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c
index bcabf65a36..d50063cbcd 100644
--- a/src/update-utmp/update-utmp.c
+++ b/src/update-utmp/update-utmp.c
@@ -29,15 +29,16 @@
#include "sd-bus.h"
+#include "alloc-util.h"
+#include "bus-error.h"
+#include "bus-util.h"
+#include "formats-util.h"
#include "log.h"
#include "macro.h"
-#include "util.h"
#include "special.h"
-#include "utmp-wtmp.h"
-#include "bus-util.h"
-#include "bus-error.h"
#include "unit-name.h"
-#include "formats-util.h"
+#include "util.h"
+#include "utmp-wtmp.h"
typedef struct Context {
sd_bus *bus;
diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c
index 49523a0a67..2298f1c2a9 100644
--- a/src/vconsole/vconsole-setup.c
+++ b/src/vconsole/vconsole-setup.c
@@ -31,9 +31,11 @@
#include <sys/ioctl.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "io-util.h"
+#include "locale-util.h"
#include "log.h"
#include "process-util.h"
#include "signal-util.h"